路由层
路由匹配
# 路由匹配
url(r'test',views.test),
url(r'testadd',views.testadd)
"""
url方法第一个参数是正则表达式
只要第一个参数正则表达式能够匹配到内容 那么就会立刻停止往下匹配
直接执行对应的视图函数
浏览器输入url的时候如果没有加/结尾,并且一组url都没有匹配成功,那么django内部
帮你做到重定向,在url后面加斜杠/后再来匹配一次url
"""
# 在settings中取消自动加斜杠再匹配
APPEND_SLASH = False/True # 默认是自动加斜杠的
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 首页
url(r'^$',views.home),
# 路由匹配
url(r'^test/$',views.test),
url(r'^testadd/$',views.testadd),
# 尾页(了解)
url(r'',views.error),
]
无名分组
"""
分组:就是给某一段正则表达式用小括号扩起来
"""
url(r'^test/(\d+)/',views.test)
def test(request,xx):
print(xx)
return HttpResponse('test')
# 无名分组就是将括号内正则表达式匹配到的内容当作位置参数传递给后面的视图函数
有名分组
"""
可以给正则表达式起一个别名
"""
url(r'^testadd/(?P<year>\d+)',views.testadd)
def testadd(request,year):
print(year)
return HttpResponse('testadd')
# 有名分组就是将括号内正则表达式匹配到的内容当作关键字参数传递给后面的视图函数
"""
有名分组和无名分组不可混用
"""
# 单个的分组可以使用多次
url(r'^index/(\d+)/(\d+)/(\d+)/',views.index),
url(r'^index/(?P<year>\d+)/(?P<age>\d+)/(?P<month>\d+)/',views.index),
注意django2.0以后 如果想使用正则表达式,只能使用re_path()来代替django1.x时代的url()
django2.0以后,默认使用path()方法来代理路由匹配,举例:
#原来的url
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
#Django2.0新语法
path('articles/<int:year>/', views.year_archive),
新语法支持url参数的类型转化。
例子里的year_archive函数接收到的year参数作为参数,并且会自动转换year为整型而不是字符串。
在新的语法path里,url字符串有以下规则:
在url里使用尖括号“<>”来捕获值
尖括号捕获值的格式<converter:name>。其中converter为路径转换器,name为参数名,如<int:year>。对于捕获的值没有路径转换器,那么它会匹配除了斜杠"/"外的所有字符作为捕获的值。
url不需要以斜杠开头
路径转换器总共如下五种:
str:匹配除了路径分隔符(/)之外的非空字符串,如果没有转换器,默认使用str作为转换器。
int:匹配0及正整数。
slug:匹配字母、数字以及横杠、下划线组成的字符串。
uuid:匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path:匹配任何非空字符串,包含了路径分隔符(/)
反向解析
# 反向解析:通过一些方法得到一个结果 该结果可以直接访问对应的url,从而触发视图函数
# 先给路由与视图函数起一个别名
url(r'^func_kkk/',views.func,name='ooo')
# 前后两端都可以调用
# 后端反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse
reverse('ooo') ##转换得到字符串/func_kkk/
# 前端反向解析
<a href="{% url 'ooo' %}">111</a>
# 无名分组反向解析 需要传入参数才能转换完整
url(r'^index/(\d+)/',views.index,name='xxx')
# 前端
{% url 'xxx' 123 %}
# 后端
reverse('xxx', args=(1,)) # 注意args必须是元组
# 有名分组反向解析 需要传入参数才能转换完整
url(r'^func/(?P<year>\d+)/',views.func,name='ooo')
# 前端
#写法1
<a href="{% url 'ooo' year=123 %}">111</a>
#写法2
<a href="{% url 'ooo' 123 %}">222</a>
# 后端
# 写法1
print(reverse('ooo',kwargs={'year':123}))
# 写法2
print(reverse('ooo',args=(111,)))
# 简便的写法 减少你的脑容量消耗 记跟无名一样的操作即可
路由分发
"""
在django中 每一个应用都可以有自己独立的templates模版文件夹、static静态文件、urls.py
也就意味基于django实现多人分组开发是非常方便的 每个人只需要专注于开发自己的app即可
当django路由匹配特别多的时候 那么总路由就可以不再直接干匹配路由和触发函数运行的事了,而仅仅做进一步的路由分发,交给每个应用的子路由来处理
"""
举例如下
# 总路由
url(r'^app01/',include('app01.urls'))
# 只要url是app01开头的url,django就会将url中app01后面的路径分发给app01下的urls.py去处理
"""
总理由url后面千万不能加$符号
"""
# 子路由
url(r'^index/$',views.index)
##上诉例子中url为/app01/index/的url最终匹配到应用app01中的index视图函数
名称空间
# 当多个应用出现相同的路由别名的时候 反向解析的时候会出现冲突
解决方法有两种
# 方式1:利用名称空间的概念,在总路由中为每个应用的url创建namespace
url(r'^app01/',include('app01.urls',namespaces='app01'))
url(r'^index/$',views.index,name='xxx')
在后端反向解析的方式:
reverse('app01:xxx')
在前端的反向解析方式
{% url 'app01:xxx' %}
# 方式2:起别名的时候加上应用前缀
url(r'^index/$',views.index,name='app01_xxx')
前后端反向解析的方式不变
reverse('app01_xxx')
{% url 'app01_xxx' %}
"""
在同一个django项目中 别名不能冲突
即只要别名不冲突 那么反向解析就不会出错!!!
"""