python web开发基于正则的动态路由映射和通过路径/路由传参(Tornado框架、Django框架)。
安装tornado:
pip install tornado
pip install Django
tornado使用:
1、在路由映射条件里用正则匹配访问路径后缀
2、给每一个正则匹配规则(?P<设置名称>)设置一个名称
3、在逻辑处理的get()方法或post()方法,接收这个正则名称,就会接收到用户访问的后缀路径
路由映射
app=tornado.web.Application(
handlers=[
(r"/" ,mainPage.IndexHandler),
#根路径
(r"/image/(.*)" ,imagee.ImageHandler),
#判断请求路径是否以image/开头,如果匹配执行ImageHandler方法
(r"/(?P<path>\w*.txt)",mainPage.txtPathHandler),
#判断请求路径是否以.txt结尾,如果匹配执行txtPathHandler方法,并把路径/后面的字符赋值给path变量
(r"/index/(?P<num>\d*)/(?P<nid>\d*)", index.indexHandler)
#判断请求路径是否以/index开头,并且后面的路径为 “数字1/数字2” 结尾,如果匹配执行MainHandler方法,
#并分别把“数字1”赋值给num,“数字2”赋值给nid
],
template_path = commonData.global_template_path,
static_path = commonData.global_static_path,
login_url = "/login"
)
#跳转到前端显示页面
class txtPathHandler(tornado.web.RequestHandler):
def get(self, path):
self.render(path)
#逻辑处理
class indexHandler(tornado.web.RequestHandler):
#定义一个类,继承tornado.web下RequestHandler类
def get(self,num,nid):
#get()方法,接收get方式请求
print(num,nid)
self.render("index.html")
基于正则的动态路由映射分页数据获取计算,分页基本显示数据:
第一步、设置正则路由映射配置,(r"/index/(?P\d*)", index.indexHandler),正则匹配访问路径,访问录index/后面可以是可以是0个或多个数字
第二步、配置逻辑处理方法,get()方法里显示对应的页面,并传值一个SHUJU全局变量列表到html模板,这个全局变量列表里是字典显示的数据
第三步、在html模板里用模板语言,循环这个列表里的字典,显示到表格里
第四步、设置用户表单提交数据,表单以post方式提交,提交到/index/1,也就是第1也
第五步、逻辑处理post()方法接收用户提交的数据,组合成字典追加到SHUJU全局变量列表里,self.redirect("/index/1")跳转到第一页,显示出添加的数据
正则匹配规则:
(?P<设置名称>)
匹配的字符集合整理:
\d 对于Unicode规则:匹配任意Unicode十进制数包括0-9。对于8位byte字符串,仅仅只匹配0-9
\s 匹配任意空格字符包括(空格,制表符,换行符,\r,\f,\v)包括许多其他的字符,比如,不同的语言分隔符也将不同,在ASCII里面,仅仅匹配[ \t\n\r\f\v]。
\S 与\s相反
\w 匹配unicode单词字符,大多数的字符,包括其他的语言的字符,数字与下划线,如果是ASCII标记,则只匹配[a-zA-Z0-9_] 。
\W 与\w相反
\number 匹配同编号组的内容,每一个组都有一个编号,编号从1开始,比如:(.+) \1 匹配’the the’ or ‘55 55’。但是不匹配’thethe’(提示:两个之间有空格,此处的匹配串中间没有空格)。这样特殊的序列只可以匹配99个组。如果序号是0或者是3位8进制数,都不会被认为是一个组,而是被处理为对应进制所代表的字符。在中括号包含的即合理,所有的数字都毫无意外的被当成字符处理。
\A 仅仅匹配字符串首部,用来说明当前位置是一个字符串的首部。
\A 在新行是没有用的,\A只匹配整个字符串的首部。
\b 匹配空字符串,但是只有在单词的后面或者前面才会匹配。一个单词背定义为一组字符序列。一般来说:\b是被定义在\W和\W之间一个分界符,或者\W与字符串首部和尾部。这也就是说:REr’\bfoo\b’匹配’foo’, ‘foo.’, ‘(foo)’, ‘bar foo baz’,但是不匹配’foobar’ or ‘foo3’.默认的Unicode字母数字都是在Unicode表达式中使用,但是也可以通过使用ASCIIflag进行切换((?A)或者re.A)。单词的分界线由归属地决定,如果使用了local flag。在单词序列中,\b代表删除符号(回溯一个字符,类比ASCII).
\B 匹配空字符串,但是只有他不是在单词首部或者尾部才会匹配,也就是说r’py\B’matches ‘python’, ‘py3’, ‘py2’, but not ‘py’, ‘py.’, or ‘py!’.\B与\b所表达的意思相反。
\Z 匹配字符串末尾。
Django 路由系统
Django路由分配系统简介
Django project目录中的urls.py文件中, 以Python [ ( ) ]的数据类型记录了可以访问到该站点的url 和 视图函数一一对应关系表,当request请求到达路由系统,Django通过request中携带的path 遍历这个关系表,匹配到对应的视图函数,break;(所以1个 url 只能从路由关系表中自上而下匹配到1个视图函数)
1、Django的路由分配系统
1个URL对应1个视图函数
from django.conf.urls import url
from django.contrib import admin
from APP import view
urlpatterns = [
url(r'^modal/',view.modal),
url(r'^域名',对应的处理函数) #注意不要忘了写 ^ 表示正则匹配以xx开头的URL
url(r'^modal_add/',view.modal_add),
url(r'^modal_del/',view.modal_del),
url(r'^modal_edit/',view.modal_edit),
]
2、在客户端通过url中的 path向后端传参数
在前端我们不仅可以通过get请求携带参数的方式向server端传数据;
https://i.cnblogs.com/%EF%BC%9Fid=1&name=alex
Django也允许通过,path路径的方式向server端传值;
注意事项:按位置,和按关键字路由系统只能用1种,不能混合使用;
1)、path正则无名分组匹配视图函数按位置传参
from django.conf.urls import url,include
from django.contrib import admin
from app1 import views
urlpatterns = [
url(r'^index/(\w+)/(\w+)/',views.index2), #酱紫的话客户端 输入:http://127.0.0.1:8000/index/a/b/也可以访问到该站点
url(r'^',views.error)
]
urlpatterns = [
url(r'^/',index), #视图函数 index(request)
url(r'^(\d{4})/\d{2}/$',timeer1), #视图函数 timeer1(request,实参1) 正则增加了分组,视图函数会增加一个参数;
url(r'^(\d{4})/(\d{2)/$',timeer2)
#视图函数 timeer2(request,实参1,实参2),视图函数需要2个形参接收;
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/$',timeer),
在路由系统定义了 几个正则分组(),在视图函数对应几个实参接收;
def timeer2(request,a1,a2):
print(a1,a2) #打印参数a1,a2 就是 2个正则表达式匹配到的结果
return Httprespose('ok')
#注意如果按位置传参的动态路由系统,必须在视图函数添加对应的参数接收!
2)、path正则有名分组匹配视图函数按关键字传参
按位置传参形参或实参错位会导致数据错乱,所以Django路由分发系统还可以以命名分组的形式匹配URL给视图函数按关键字传参;
from django.conf.urls import url,include
from django.contrib import admin
from app1 import views
urlpatterns = [
url(r'^index/(P<n1>\w+)/(P<n2>\w+)/',views.index,name="test"),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/$',timeer),
url(r'^',views.error), ]
#注意如果在路由系统正则内部定义了关键字n1,n2,视图函数接收参数也必须是 n1,n2;
urlpatterns = [
# url(r'^/',index), #index(request)
# url(r'^(\d{4})/\d{2}/$',timeer), #timeer(request,2014) 正则增加了分组,视图函数会增加一个参数;
# url(r'^(\d{4})/(\d{2)/$',timeer1) , #timeer(request,2014,12) 视图函数需要两个形参接收
url(r'^(?P<year>\d{4})/$(?P<month>\d{2})',timeer2) #timeer(request,year=2017,month=6) 正则设置了有名分组,视图函数使用关键字传参
]
在视图函数定义2个关键字参数, 接收 2个正则表达式匹配到的后缀;
def index(request,n1,n2):
print(n1,n2) #注意必须和 路由系统中的一致
return HttpResponse('OK')
3)、URL path传值应用
有了动态路由就 可以不用在 url?nid=8这样传值了!
终止符:^edit$ 可以精确限制匹配URL的后缀内容
伪静态:url(r’^edit/(\w+).html$’, views.edit) 装作成静态网站的url可以 提高 SEO高权重 百度排名靠前
url(r'^student_del/(.*).html/',views.student_del),
<a href="/student_del/{{row.id}}.html/">删除</a></td>
def student_del(request,args1):
return HttpResponse('nihao')
3、路由分发
1个Django 项目里面有多个APP目录大家共有一个 url容易造成混淆,于是路由分发让每个APP的拥有了自己单独的url;
from django.conf.urls import url,include
from django.contrib import admin
from app1 import views
urlpatterns = [
url(r'^app1/',include('app1.urls')),
url(r'^app2/',include('app2.urls')), #注意include的是字符串形式的 文件路径;
url(r'^',views.error),
]
酱紫就可以在每个 Django目录下面写自己的 URL了
4、路由别名(应用站点权限管理)
1)、什么是路由别名?
给Django路由分发系统 URL–视图函数对应关系命个名,
然后在模板中{% url “test” i i1%}反生成 访问该站点URL,
或者在视图函数中reverse()反向生产当前访问URL;
2)、作用
保证前后端数据一致性,后端修改了匹配URL,不用在前段更改;
from django.conf.urls import url,include
from django.contrib import admin
from app1 import views
urlpatterns = [
url(r'^index/(?P<n1>\w+)/(?P<n2>\w+)/',views.index,name="alex"), 给这个URL起别名 alex
url(r'^',views.error),
]
在视图函数使用 reverse(“别名”, args=(1, 2)) 反生 位置参数动态路由的 别名
def index(request,n1,n2):
print(reverse("test", args=(1, 2)))
return render(request,'index.html',{'i':1,'i1':2})
在视图函数使用 reverse(“别名”,kwargs={“关键字参数”:1,“关键字参数”:2 }反生 关键字参数动态路由的 别名
def index(request,n1,n2):
print(reverse("test",kwargs={"n1":1,"n2":2 }))
return render(request,'index.html',{'i':1,'i1':2})
在模板中反生 URL
注意 在视图函数中 return render(request,‘index.html’,{‘i’:1,‘i1’:2})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>{{ i }}</p>
<p>{% url "test" i i1%}</p>
</body>
</html>