路由匹配
urls.py
from django.conf.urls import url
urlpatterns = [
url(正则表达式, views视图函数,参数,别名)
]
参数分析:
正则表达式:一个正则表达式字符串
views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
参数:可选的要传递给视图函数的默认参数(字典形式)
别名:一个可选的name参数
注意事项
urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
每个正则表达式前面的’r’ 是可选的但是建议加上。
补充说明
是否开启URL访问地址后面不为/跳转至带有/的路径的配置项APPEND_SLASH=True
Django settings.py配置文件中默认没有 APPEND_SLASH 这个参数,但 Django 默认这个参数为 APPEND_SLASH = True。 其作用就是自动在网址结尾加’/’
访问http://127.0.0.1:8000/test 时,默认将网址自动转换为 http://127.0.0.1:8000/test/ 。
如果在settings.py中设置了 APPEND_SLASH=False,此时我们再请求http://127.0.0.1:8000/test 时就会提示找不到页面
无名分组
urlpatterns = [
url(正则表达式, views视图函数,参数,别名)
]
在第一个参数正则表达式,给正则条件加上(),进行分组
然后就会报错:test() takes 1 positional argument but 2 were given
说我们给了两个参数
views.py
在启动
总结:
无名分组----路由匹配时,如果对正则表达式进行分组,那么会传入除了request参数外,还会分组后匹配到的内容
有名分组
有名分组其实就是对正则表达式分组之后,对分组的内容起了个别名
同时传入视图函数的时候,需要特定这个别名的关键字参数来接受
views.py
形参中必须要有 正则表达式分组起了别名的 关键字参数
无名分组和有名分组不能在一个url中混用,但是可以某种类型重复使用
反向解析
通过反向解析可以获取到一个结果 该结果可以访问到一个路由
通过name属性来命名,注意:多个 URL 命名是不可以重复的
urlpatterns = [
url(r'^home/', views.home, name= 'home'),
那么,给 URL 命名的应用场景是什么?
URL反向解析–前端
在urls.py中给某个路径的后缀起了别名之后;
在模板 (HTML文件)中 就可以直接根据{% url’别名’ %}直接拿到起别名的路径,而不是手动拼接路径!!
这样做的好处在于,如果有修改url的时候,就不需要手动到 模板文件中 一个一个地修改了
urlpatterns = [
url(r'^home/', views.home, name= 'home_view'),
url(r'^index/', views.index, name= 'index_view'),
]
views.py
from django.shortcuts import render, HttpResponse, redirect
def home(request):
return render(request, 'home.html')
def index(request):
return HttpResponse('from index')
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/index/">点我!要你好看</a>
<a href="{% url 'index_view' %}">点点点!!!!!</a>
</body>
</html>
修改URL
urlpatterns = [
url(r'^home/', views.home, name= 'home_view'),
url(r'^index666/', views.index, name= 'index_view'),
]
会发现反向解析的链接,能够自动解析新的路径!!
URL反向解析–后端
方式一:reverse模块
views.py文件
# 模块导入
from django.shortcuts import redirect, reverse
def func(request):
_url = reverse('index_view')
return redirect(f'{_url}')
urls.py
urlpatterns = [
url(r'^home/', views.home, name= 'home_view'),
url(r'^index/', views.index, name= 'index_view'),
url(r'^func/', views.func, name= 'func_view'),
]
结果:
“GET /func/ HTTP/1.1” 302 0
“GET /index/ HTTP/1.1” 200 10
方式二:
views.py文件
# 模块导入
from django.shortcuts import redirect
def func(request):
# 可以直接写别名,也会自动跳转
return redirect('index_view')
“GET /func/ HTTP/1.1” 302 0
“GET /index/ HTTP/1.1” 200 10
无名分组反向解析
urlpatterns = [
url(r'^test/(\d+)/',views.test,name='test_view'),
]
def test(request, a):
res = reverse('index_view')
print(res)
return HttpResponse('from test')
当url中对正则表达式进行分组之后,视图函数反向解析出/test/之后,需要继续做后缀的匹配,如果不给一个确切的值的话,那么/test/1/、/test/2/、/test/666/都符合匹配规则,所以视图函数还需要一个参数来匹配/test/之后的参数
后端语法:
def test(request,a):
res = reverse('index_view', args=(666,))
print(res)
return HttpResponse('from test')
结果展示为:/test/666/
如果无名分组有多个,那么在args括号内一次传入多个即可
前端模板语法:
{% url ‘index_view’ 666 %}
有名分组反向解析
urlpatterns = [
url(r’^test/(?P<user_id>\d+)/',views.test,name=‘test_view’),
后端语法:
def test(request, user_id):
res = reverse(‘index_view’, kwargs={‘user_id’:666, })
print(res)
return HttpResponse(‘from test’)
前端模板语法
{% url ‘index_view’ user_id=666 %}
名称空间
当一个项目的应用非常多时,在urls.py文件中urlpatterns列表中的路由会非常多,这样会导致非常不好管理路由,这时考虑将一个urls.py文件拆分开,每一个应用单独新建一个urls,py,通过总的路由文件对每个应用的路由文件进行统筹管理
子路由中的路由配置还是按照之前的方式,但是总路由的配置需要改变
导入模块include
from django.conf.urls import include, url
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls')), # 可以包含其他的URLconfs文件
url(r'^app02/', include('app02.urls')), # 可以包含其他的URLconfs文件
]
路由匹配时,如果匹配到/app01/会直接到app01.urls.py文件中去继续做路由匹配
路由分发
Django 项目中有两个应用–app01与app02,分别有其各自的urls.py
如果两个项目都有一个url(r’^index/',views.index,name=‘index_view’), 即多个应用出现路由命名冲突的情况!
此时,对index_view这个别名进行反向解析时,能够解析出是属于app01的,还是app02的呢?
直接说结论:当一个项目中有相同的路由命名,只会识别到最后一个起了这个名字的路由,其他的相同命名的路由,无法被反向解析出来
解决办法:在总路由进行路由分发的时候,给每个应用进行命名空间namesapce=的起别名操作
创建多个应用 并去配置文件中注册
INSTALLED_APPS = [
‘app01’,
‘app02’
]
总路由:
from django.conf.urls import include, url
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls',namespace='app01')),
url(r'^app02/', include('app02.urls',namespace='app02')),
]
各自的app的urls.py
这样在各自的视图函数进行反向解析的时候会有不同的提示
其实,该问题的解决方法还可以在给路由重命名时,加上应用的前缀app01_index_view这样可以不使用名称空间,同样达到相同的效果