Django(路由)
一.URL模式
Django在检查URL模式之前,会移除每一个申请的URL开头的斜杠(/),因此我们在form表单中如果要访问127.0.0.1:8000/index/地址,直接写/index/即可。 URL模式要求尾部要有一个斜杠,因此在urls.py中要在url后添加一个/ #注意:在浏览器输入127.0.0.1:8000/login发送给Django后端,django会回一个重定向/login/,然后浏览器重新请求这个网址。我们在浏览器可以看到是两个请求 settings.py中配置APPEND_SLASH=True,浏览器输入../login会重定向加上/,如果APPEND_SLASH=False,浏览器输入什么就是什么,不会补全 # redirect重定向 // 表示在http:之后添加 / 表示在当前ip和端口之后添加 不加斜杠表示在当前路径之后添加
二.正则路由
Django1.11中的路由使用url('xx',views.xx),Django2.0版本之后使用path、re_path(),Django版本1中的url相当于版本2中的re_path
1.分组
from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ #url(r'^admin/', admin.site.urls), url(r"^home/([0-9]{4})/([0-9]{2})",views.home), ] #url中的括号()相当于分组,以上分2组,括号中的内容都作为参数传递给views.py中的home函数
from django.shortcuts import render,HttpResponse,reverse,redirect #home函数使用year、month接受分组完成的2个参数 def home(req,year,month): return render(req,"home.html",{"year":year,"month":month})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 欢迎进入{{ year }}年{{ month }}日 </body> </html>
2.命名分组
from django.conf.urls import url,include from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^home/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})",views.home), ] #在django的url中,括号为分组,(?P<year>[0-9]{4})是为其添加一个组名,那么views.py中的home函数接受时的参数必须为"year"和"month"
三.路由分发(include)
在一个项目中,会有很多的app,这就用到路由分发
新建app(python manage.py startapp app02)
如上图:有两个app(app01和app02),我们在浏览器输入网址后,会按照django的默认配置先找到djangotest中的urls.py,因此,我们在djangotest中的urls.py中添加路由分发:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^app01/",include('app01.urls')), #浏览器输入127.0.0.1:8000/app01/xx,会从app01中的urls.py找到xx url(r"^app02/",include('app02.urls')), ]
from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^test/,views.test'), ] #浏览器输入127.0.0.1:8000/app01/test,会找到当前py文件中的url(r'^test/,views.test')
from django.conf.urls import url from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^test/",views.test), ] #浏览器输入127.0.0.1:8000/app02/test,会找到当前py文件的test
四.命名URL和反向解析
命名URL简单来说就是起个别名。举个简单例子:
url(r'^home', views.home, name='home'), # 给我的url匹配模式起名为 home url(r'^index/(\d*)', views.index, name='index'), # 给我的url匹配模式起名为index,未命名分组 url(r'^index/(?P<a>\d{4})/(?P<b>\d{2})/',views.index,name="indextest") #给url匹配模式起名为indextest,命名分组为a、b
反向解析:通过name="home"找到其对应的url
两种方法: 1.通过模板找 2.通过引入reverse找
1.模板中的写法:
{% url 'home' %} #这样会找到name='home'的相对应的url {% url 'index' '10'%} #找到name='index'的url为'^index/(\d*)',然后将'10'传递给(\d*) {% url 'indextest' a='2019' b='10' %} #找到name='indextest'的url为'^index/(?P<a>\d{4})/(?P<b>\d{2})/',将2019和10传给url中的参数,模板中的键和url匹配模式中的分组名必须一致
2.views函数中引用:
from django.urls import reverse def redirect_to_year(request): return redirect(reverse("home") #return redirect(reverse("index",args=('10',))) #找到name='index'的url为'^index/(\d*)',然后将'10'作为参数传递给(\d*) #return redirect(reverse("indextest",kwargs={"a":1995,"b":10})) #必须是a和b
五.命名空间
如果我们在多个不同的app中有相同的URL命名,那么反解析可能会找不到。
错误示例:
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^app01/', include('app01.urls')), url(r'^app02/', include('app02.urls')), ] #1.app01中的 from django.conf.urls import url urlpatterns = [ url(r'^xx/', views.xx,name="home"), ] #1.app02中的 from django.conf.urls import url urlpatterns = [ url(r'^xx', views.xx,name="home"), ] #如此,我们无论通过模板反解析还是通过reverse反解析,找到的可能是app01中的url,也可能是app02中的url
解决方法:命名空间namespace
from django.conf.urls import url,include from django.contrib import admin urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^app01/', include('app01.urls',namespace='app01')),#app01/home/ url(r'^app02/', include('app02.urls',namespace='app02')), ]
#1.app01中的 from django.conf.urls import url urlpatterns = [ url(r'^xx/', views.xx,name="home"), ] #1.app02中的 from django.conf.urls import url urlpatterns = [ url(r'^xx', views.xx,name="home"), ]
使用:
#先从项目中的urls.py中找到namespace为app01的,再从app01中的urls.py找到name=home的 后端:reverse('命名空间名称:别名') -- reverse('app01:home') hmtl:{% url '命名空间名称:别名' %} -- {% url 'app01:home' %}