Django之路由层
Django之路由层 |
一、概述
路由即请求地址与视图函数的映射关系,在Django中路由默认配置在urls.py中。
二、URL配置
URL配置(URLconf)就像Django所支持网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。
1 urlpatterns = [ 2 url(正则表达式,views视图函数,参数,别名), 3 ]
做个简单的实例:
(1)urls.py文件
from django.conf.urls import url from django.contrib import admin from app01 import views #导入模块views.py urlpatterns= [ url (r'^admin/', admin.site.urls), url (r'^index/',views.index),#新增一条,推荐每一条后加逗号 ]
(2)views.py文件
from django.shortcuts import render,HttpResponse #导入HttpResponse,用来生成响应信息 #新增视图函数index def index(request): return HttpResponse("hello world")
测试:
python manage.py runserver 8001 #在浏览器输入:http://127.0.0.1:8001/index 会看到hello world
三、分组
什么是分组?为何要分组呢?好比我们开发一个博客系统,当我们需要根据文章的id查看指定文章时,浏览器在发送请求时需要向后台传递参数(文章的id号),可以使用http://127.0.0.1:8001/blog/?id=6,也可以直接将参数放到路径中http://127.0.0.1:8001/blog/3
针对后一种方式Django就需要直接从路径中取出参数,这就用到了正则表达式的分组功能了,分组分为两种:无名分组与有名分组。
1.无名分组
(1)urls.py文件
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), #下述正则表达式会匹配url地址的路径部分为:aarticle/年份,匹配成功的分组部分会以位置参数的形式传给视图哈数,有几个分组就传几个位置参数 url(r'^article/(\d{4})$',views.article_year), #无名分组 ]
(2)views.py文件
from django.shortcuts import render,HttpResponse #需要额外增加一个形参用于接收传递过来的分组数据 def article_year(request,y): return HttpResponse("当前的年份为:%s"%y)
测试:
python manage.py runserver 8001 #在浏览器输入:http://127.0.0.1:8001/article_year/2019 会看到:当前的年份为:2019
2.有名分组
(1)urls.py文件
from django.conf.urls import url from django.contrib import admin from blog import views urlpatterns = [ url(r'^admin/', admin.site.urls), #该正则会匹配url地址的路径部分为:article/年份/月份,匹配成功的分组部分会以关键字参数(year=匹配成功的数字&month=匹配成功的数字)的形式传给视图函数,有几个有名分组就会传几个关键字参数 url(r'^article/(?P<year>\d{4})/(?P<month>\d{2})',views.article_year_month), #有名分组 ]
(2)views.py文件
from django.shortcuts import render,HttpResponse #需要额外增加两个形参,形参名必须为year和month def article_year_month(request,year,month): return HttpResponse("当前的年份为%s,月份为%s"%(year,month))
测试:
python manage.py runserver 8001 #在浏览器输入:http://127.0.0.1:8001/article/2019/10 会看到:当前的年份为2019,月份为10
有名分组和无名分组都是为了获取路径中的参数,并传递给视图函数,区别在于无名分组是以位置参数的形式传递,有名分组是以关键字参数的形式传递。无名分组和有名分组不能混合使用。
四、路由分发
随着项目功能的增加,app会越来越多,路由就越来越多,每个app都会有属于字节的路由,如果再将所有路由都放到一张路由表中,会导致结构不清晰,不便于管理,所以我们应该将app自己的路由交给自己管理,然后在总路由表中做分发。
1.在app01下手动创建urls.py来存放自己的路由
(1)app01下的urls.py文件
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^article/(\d{4})$',views.article_year), ]
(2)app01下的views.py文件
from django.shortcuts import render,HttpResponse def article_year(request,y): return HttpResponse("当前的年份为:%s"%y)
(3)在总的urls.py文件中(mysite文件夹下的urls.py)
from django.conf.urls import url,include #导入include from django.contrib import admin #总路由表 urlpatterns = [ url(r'^admin/', admin.site.urls), #include函数就是做分发操作的 url(r'^app01/$',include('app01.urls')), ]
测试:
python manage.py runserver 8001 #在浏览器输入:http://127.0.0.1:8001/app01/aarticle/2019 会看到:当前的年份为:2019
五、反向解析
在软件开发初期, url地址的路径设计可能并不完美,后期需要进行调整,如果
项目中很多地方使用了该路径,一旦该路径发生变化,就意味着所有使用该路径
的地方都需要进行修改,这是一个非常繁琐的操作。
解决方案就是在编写一条url时,可以通过参数name为url地址的路径部分起一个别名,项目中就可以通过别名来获取这个路径。以后无论路径如何变化别名与路径始终保持致。
上述方案中通过别名获取路径的过程称为反向解析
我们来实现一个简单的反向解析实例:
(1)urls.py文件
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^register/$',views.register,name="reg"), #路径register/的别名为reg url(r'^login/$',views.register,name="log"), #路径login/的别名为log ]
(2)views.py文件
from django.shortcuts import render,HttpResponse,redirect,reverse #引入redirect类,用于重定向页面 引入reverse类,用于反向解析 def register(request): if request.method=="POST": user=request.POST.get("user") if user=="alex" and pwd=="123456": url = reverse('log') #reverse会将别名'log'反向解析成路径:/login/ return redirect(url) #页面跳转 return HttpResponse("错误!") return render(request,"register.html") #当不是POST请求时,返回register.html页面,页面中的{% url 'reg' %}会被反向解析成路径:/register/ def login(request): name="alex" return render(request,"login.html",locals())
(3)register.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> {% csrf_token %} <!--强调:必须加上这一行,而且在开始位置加上--> {% load staticfiles %} <title>Title</title> </head> <body> <h1>学生注册</h1> <!--强调:reg必须加上引号--> <form action="{% url 'reg' %}" method="post"> <p>姓名<input type="text" name="user"></p> <p>年龄<input type="text" name="age"></p> <p>爱好 <input type="checkbox" name="hobby" value="1">篮球 <input type="checkbox" name="hobby" value="2">足球 <input type="checkbox" name="hobby" value="3">乒乓球 </p> <p><input type="submit">提交</p> </form> </body> </html>
(4)login.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>hello {{ name }}</h1> <form action=""> 用户名<input type="text"> </form> </body> </html>
测试:
python manage.py runserver 8001 #在浏览器输入:http://127.0.0.1:8001/register 会看到登录页面,当用户名输入alex会跳转到login.html
总结:在views.py文件中,反向解析的使用:url=reverse('log'),在模板register.html文件中,反向解析的使用{% url 'reg' %}
注意:当我们项目下创建多个app,每个app下针对匹配的路径起了别名不能重复,否则在反向解析时会出现覆盖。