今日是路由层学习: 3.路由匹配 3.1 正则表达式的特点: 一旦正则表达式能够匹配到内容,会立刻结束匹配关系 直接执行对应的函数。相当于采用就近原则,一旦找到就不再继续往下走了 重点: 正则表达式开头用 ^ 表示 (开头必须要有) 正则表达式结尾用 $ 表示 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/', views.test), url(r'^testadd/', views.testadd), ] 3.2 settings.py文件中配置请求的访问路径自动加斜杠的功能 默认情况下,是TRUE。 #取消django自动让浏览器加斜杠的功能 APPEND_SLASH = False 添加配置后 例如: http://127.0.0.1:8000/testadd进行请求会出现404页面 取消配置后,尾部django会自动添加/ http://127.0.0.1:8000/testadd/ 请求访问成功 举例: 1.路径如下: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'testadd/', views.testadd), ] 请求路径中的漏洞: http://127.0.0.1:8000/wwwwwwwwwwwwwtestadd/ 请求结果:请求成功 解决方法: 在url(r'testadd/', views.testadd)中的testadd/前部添加 ^ 符号 代表请求路径 从...开始 正确路径如下: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^testadd/', views.testadd), ] 2.路径如下: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^testadd/', views.testadd), ] 请求路径中的漏洞: http://127.0.0.1:8000/testadd/wwwwwwwwww 请求结果:请求成功 解决方法: 在url(r'^testadd/', views.testadd)中的testadd/尾部添加 $ 符号 代表请求路径 以...结束 正确路径如下: urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^testadd/$', views.testadd), ] 注意事项: 路由匹配只匹配请求的url路径部分,不匹配 ?后面的get携带的字段值参数,如下: http://127.0.0.1:8000/testadd/?username=jsaon 4.无名分组---->用位置形参 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/([0-9]{4})', views.test), url(r'^testadd/', views.testadd), ] 对应报错的语句: url(r'^test/([0-9]{4})', views.test), test() takes 1 positional argument but 2 were given 什么是无名分组? 当你的路由中有分组"([0-9]{4})"的正则表达式,那么在匹配到内容时执行函数的时候, 会将分组内正则表达式匹配到的内容当做位置参数传递给视图函数,那么 就需要在函数中添加一个形参,如下: def test(request,分组对应的形参): 5.有名分组----->用关键字实参 (?P<year>\d+) urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^testadd/(?P<year>\d+)', views.testadd), ] url(r'^testadd/(?P<year>\d+)', views.testadd), testadd() got an unexpected keyword argument 'year' 什么是有名分组? 当你的路由中有分组并且给分组起了别名(year),那么在匹配内容的时候, 会将分组内的正则表达式匹配到的内容(year)当做关键字参数传递给视图函数, def testadd(request,year): year的值是用户在浏览器输入的url地址中对应的一块数据 比如用户输入的地址是:http://127.0.0.1:8000/testadd/2222,请求成功, 那么year对应的数据就是 year=2222 关键字参数: def func(x,y): print(x) print(y) func(x=1,y=2) 位置参数: def func(x,y): print(x) print(y) func(1,2) 利用有名和无名分组,我们就可以在调用视图函数之前给函数传递额外的参数。 django中有名分组和无名分组不能同时混合使用!!! 但是同一种分组的情况下,可以使用多次, 无名可以有多个, 有名可以有多个, 但是就是不能混合使用,其实写多个也没有啥意思,知道这种形式即可 url(r'^index/(\d+)/(\d+)/',views.index) url(r'^index/(?P<args>\d+)/(?P<args>\d+)/',views.index) 6.第一种情况反向解析 (通俗)何为反向解析,就是通过A---->(访问到了)B去了!!! (专业)何为反向解析,就是根据一个别名,动态解析出一个结果, 该结果可以最直接访问到对应的url 1.前端反向解析: 在html页面中编写 {% url 'xxx' %} <p><a href="{% url 'xxx' %}">111111</a></p> 2.后端反向解析: 在views.py文件中编写 1.首先导入reverse模块: from django.shortcuts import render,HttpResponse,redirect,reverse 2.在对应视图函数中编写后端反向解析代码 url=reverse('xxx') 7.第二种情况反向解析 1.无名分组的反向解析,在解析的时候,你需要手动指定正则匹配的内容是什么 url(r'^home/(\d+)', views.home,name='xxx'), Reverse for 'xxx' with no arguments not found. 1 pattern(s) tried: ['home/(\\d+)'] 翻译:'xxx'的反转,没有找到参数。['home/(\\d+)'] 解决方法: 在前端对应的html文件中,解析代码中添加一个匹配正则的参数即可(例如:12) {% url 'xxx' 12 %} 该数字通常是数据的主键值!!! <p><a href="{% url 'xxx' 12 %}">111111</a></p> 注意事项:在后端views.py文件中配置一个位置参数(yyy)接收正则 def home(request,yyy): return HttpResponse('Home') 综上所述,所以总结如下: 无名分组前端反向解析: <p><a href="{% url 'xxx' 12 %}">111111</a></p> 无名分组后端反向解析: 后端反向解析需要后端views.py文件中,对应的函数中的位置参数匹配到正则表达式即可 通过访问http://127.0.0.1:8000/index/,点击'111111',跳转报错, 报错信息:home() takes 1 positional argument but 2 were given 原因是home函数缺少了一个位置参数,所以下面的home函数需要配置一个位置参数(yyy) 1.def home(request,yyy): return HttpResponse('Home') 之后后端对应解析如下: 添加一个args=(参数,),注意括号内的逗号不能省略 2.def get_url(request): url=reverse('xxx',args=(1,)) #必须加逗号,作为元组 print(url) return HttpResponse('get_url,大宝贝') 在get _url函数中,如果反转解析忘记配置args =(参数,)了,就会报下面的错误: Reverse for 'xxx' with no arguments not found. 1 pattern(s) tried: ['home/(\\d+)'] 'xxx'的反转,没有找到参数。 8.第三种情况反向解析 无名分组不是真的无名,而是没有固定的名字; 有名分组是因为有固定不变的名字,所以称之为有名分组; 下面的知识点仅作了解: 1.有名分组的反向解析,在解析的时候,需要手动指定,正则匹配的内容是什么呢? 正规的写法是: url(r'^home/(?P<year>\d+)', views.home,name='xxx'), 前端: 可以直接用无名分组的情况 <p><a href="{% url 'xxx' 12 %}">111111</a></p> 也可以使用规范的写法!!!书写麻烦了解即可 <p><a href="{% url 'xxx' year=1232 %}">111111</a></p> 后端: 可以直接用无名分组的情况 url=reverse('xxx',args=(1,)) 也可以使用规范的写法!!!书写麻烦了解即可 url=reverse('xxx',kwargs={'year':666}) 9.无名有名反向解析结合使用 以编辑功能为例 url(r'^edit_user/(\d+)/',views.edit_user,name='edit') def edit_user(request,edit_id): #edit_id就是用户想要编辑数据的主键值 pass {% for user_obj in user_list %} <a href='/edit_user/{{user_obj.id}}'>编辑</a> <a href='{% url 'edit' user_obj.id %}'>编辑</a> #反向解析 {% endfor %} 10.路由分发 前提: 在django中所有的app都可以有自己独立的urls.py templates static文件 作用:为大项目解耦合,分功能开发,互相之间不干扰,每个人只负责自己的app即可 项目经理只需要将所有人开发的app整合到一个空的django项目中, 然后再settings配置文件注册,再利用路由分发将多个app整合到一起, 即可完成大项目的拼接。 路由分发解决的就是项目的总路由匹配关系过多的情况 使用路由分发,会将总路由不再做匹配的活而仅仅是做任务分发: 请求来了之后,总路由不做对应关系,只询问你要访问哪个app的功能, 然后将请求转发给对应的app去处理。 创建第二个app 1.Tools--->Run manage.py Task... 2.manage.py@day51 > startapp app02 然后在settings配置文件中配置对应app名字 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'app02' ] 并分别在app下创建urls.py文件 3. 总路由只需要将所有的app的urls.py导入即可。 总路由中导入include模块: from django.conf.urls import url,include 总路由中导入各个应用下的urls.py文件,as 是起别名: from app01 import urls as app01_urls from app02 import urls as app02_urls 在对应的应用下的urls.py文件中书写下面代码: 例如:app01应用的urls.py文件中书写: from django.conf.urls import url from app01 import views urlpatterens = [ #这里面写该应用下的路由 url(r'^index/', views.index) ] 总路由分发: 总路由中使用include做分发 因为app01、app02下的路由、对应视图函数都含有def reg(request):函数, 所以总路由为了做好区分,在总路由中分别使用各个应用名的前缀来做区分, 笨方法总路由: from app01 import urls as app01_urls from app02 import urls as app02_urls urlpatterns = [ url(r'^app01/',include(app01_urls)), url(r'^app02/',include(app02_urls)) ] 总路由分发注意事项: 总路由里面不能以 $ 符号结尾 在urlpatterns中r'^app02/'$(千万不能加$符号),不然路径都是匹配不上的 为了解决总路由中每次频繁导入app应用的问题: django推出了最最简单的总路由分发方法: 特点: 1.无需频繁导入 2.不用频繁加应用名后缀 那么该方法是什么呢? 新方法总路由: 1.不要导入语句 2.不再使用应用名前缀,使用 (应用名.urls) #from app01 import urls as app01_urls #from app02 import urls as app02_urls urlpatterns = [ url(r'^app01/',include(app01.urls)), url(r'^app02/',include(app02.urls)) ] ||||||||||||||筛检上面不用的代码,如下:|||||||||||||||||| urlpatterns = [ url(r'^app01/',include('app01.urls')), url(r'^app02/',include('app02.urls')) ] 子路由app01: from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^reg/', views.reg), ] 子路由app02: from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^reg/', views.reg), ]
来源:https://www.cnblogs.com/ludundun/p/11938228.html