路由控制之简单配置
-
看urls.py中的导包
from django.urls import path,re_path
path和re_path区别在于re_path是用正则匹配路由路径,而path就是纯字符串匹配
所以这里用re_path是为了展示1.0也是有这个功能
在urls中添加路由列表,第一个参数是url路径中一旦匹配到这个字符串,就会执行views中的函数,
第一个参数是支持正则写法的,比如以case/case01开头,但不限定结尾
可以看到只要是以case/case01开头 后面无论添加什么 都返回一样的内容
为了演示效果,views文件中,导入HttpResponse方法先.
-
路由正则分组概念
现在先在views新写一个函数case02,可以看到新增了一个新参,后面会提到
在urls中我们对路由列表的正则表达式 添加了一个括号(),这个在正则代表分组的意思,这个分组如果配到的话,会连同request一起传给views里的函数,所以必须要有2个形参
访问结果如下,年份会随着你的url变化而变化,
然而路由中的分组可以有很多个,注意的一点就是无论是几个分组,都要相应加上request一起传给函数,函数的形参接受数量要一直
-
路由正则分组规则不严格,导致从上至下解析错误解析的问题
我们看下面,case02这里我们把前面正则的$结尾限定符号去掉.那么当访问的Url为http://127.0.0.1:8000/case/2088/02/
时候会自上而下优先访问case02函数
本意是要访问case03的,结果因为2条正则规则都符合,自上而下运行,就优先执行了上面一条规则,运行了case02, 要避免这个情况就把$加上去re_path(r"^case/([0-9]{4,})/$",case02),
分组总结: -
如果从URL中获取一个值,那么在周围放置一堆圆括号
-
根路径后面的第一个路径不需要加反斜杠,比如case是对的/case反而是错误的
-
每个正则前面建议加上'r' 代表字符串中任何字符都无须转义
其他的例子,便于理解
路由控制之有名分组
- 上面的例子中函数传参是根据位置传的,但是如果我们需求是根据形参名传呢????
我们需要在urls路由控制参数中用固定的?P<变量名>
添加到正则的匹配语法中去,比如([0-9]{4,})
就变成了?P<year>([0-9]{4,})
所以re_path(r"^case/(?P<year>[0-9]{4,})/(?P<mon>[0-9]{2})/$",case03)
会传参数request,year= mon=
我们在case03中故意把年份和月份写反,
但是输出结果还是正常
路由控制之分发解耦
前面的例子中,我们把项目所有的路由分发策略都写在了项目下的urls.py,如果我们有100个app呢,如果每个app下又有100个子页面呢? 我们需要进一步解耦,在项目路由表中按照应用名分发,然后在应用的包中再创建一个urls.py,用于该应用下的路由分发,这样就解耦开来了
- 第一步需要在项目urls中导入include包
from django.urls import path,re_path,include
- 第二步在应用下创建urls文件,然后在项目路由中添加分发规则,如果是my_app开头的全部分发到my_app.urls中
re_path(r"my_app/",include("my_app.urls"))
- 第三部my_pp中的urls创建规则
from django.urls import path,re_path from my_app.views import * urlpatterns = [ re_path(r"^case/(?P<year>[0-9]{4,})/(?P<mon>[0-9]{2})/$",case03), path("mytest/",my_test) ]
- 访问页面
- 整个代码页面
路由控制之登录验证示例
如前端网页视图,我们平时用get访问是访问网页,但是当我们在输入了账号密码按回车后又是需要递交参数的,
如果我们get访问的url和<form action="http://127.0.0.1:8000/test/" method="post">
都是http://127.0.0.1:8000/test/ 要怎么区分这两次访问呢?
==注:如果form action 递交数据还是跳回get的url地址,那么前面的ip可以省略 <form action="/test/" method="post">
在全局的路由分发中urls代码如下
from my_app.views import *
urlpatterns = [
path('test/', beijing_time),
]
视图中的views代码如下: 可以看到这个形参request会把请求的方式和内容,并且把提交的信息以字典形式可以轻松获取.
def beijing_time(request):
import time
c = time.time()
b= time.localtime(c)
a = time.strftime("%Y-%m-%d %H:%M:%S")
if request.method=="POST": #这里区分提交方式,如果是POST就开始验证账号密码.
if request.POST.get("user") == "sxf" and request.POST.get("pwd")=="123":
return HttpResponse("登陆成功")
else:
return HttpResponse("登陆失败")
elif request.method=="GET":
return render(request,"test.html",{"data":a})
路由控制之反向解析1
还是上面的例子,根据路由分发规则,我们get访问的url是http://127.0.0.1:8000/test/
,然后POST请求的地址也是http://127.0.0.1:8000/test/
POST请求的HTML文件和GET请求是同一个HTML文件,但是考虑到后期get的请求地址会变动,那么我们改了get请求的路由规则,比如把test改成login
from my_app.views import *
urlpatterns = [
path('login/', beijing_time),
]
但是在我们输入了账号密码递交,却显示404了,因为action的网址还没改,因为把他写死了.
我们需要用反向解析给路由分发器中取个别名 name="log"
from my_app.views import *
urlpatterns = [
path('login/', beijing_time,name="log"),
]
然后HTML文件中用蒙版语法引用这个POST地址,语法为{% url 别名 %}
<form action="{% url 'log' %}" method="post">
这样无论前面路由地址怎么更改,都可以获取到路由中的地址路径
流程控制之反向解析2
反向解析还有种用法,这种用法是在view函数中根据路由分发器中的name变量
# 项目的路由分发器代码如下
urlpatterns = [
re_path(r"my_app/",include("my_app.urls"))
]
my_app中的分发路由如下
urlpatterns = [
re_path(r"^case3/([0-9]{4,})/([0-9]{2})/$",case03,name = "mytest_reverse3"),
# 路径为my_app/case/2019/02/
path("mytest/2003",my_test,name="mytest_reverse")
#路径为my_app/mytest/2003
]
views中的函数如下
def case03(request,mon,year):
print(reverse("mytest_reverse2",args=(2004,"09",)))
return HttpResponse("你输入的年份是%s,月份是%s"%(year,mon))
def my_test(request):
print(reverse("mytest_reverse"))
return HttpResponse("my_test页面")
- 以路径
http://127.0.0.1:8000/my_app/mytest/2003
为例,会运行my_test函数,会打印输出/my_app/mytest/2003
reverse("mytest_reverse")
会解析出mytest_reverse这个别名的url地址,这里的url是写死的,下面举例一个正则的 - 以路径
my_app/case/2019/02/
为例,会运行 case03 函数,别名是mytest_reverse3,那么在case03函数中reverse("mytest_reverse2",args=(2004,"09",))
- 因为分发路由中的re_parth中有了2个分组,因此我们在reverse函数中要添加2个参数,参数必须符合分组的正则表达规则,打印输出的内容为
/my_app/case/2004/09/
- 这里强调的一点是:函数里的reverse()进行的反向解析和所在哪个函数没有关系 假设我们访问路径为
http://127.0.0.1:8000/my_app/mytest/2003
可以看到我们把2个反向解析都放在一个My_test函数中,他的会因为路径找到my_test这个函数执行,然后reverse反向解析会根据别名解析到下面2个路由分发的规则中
根据mytest_reverse2别名解析里面的url解析规则,在根据2个分组传入参数2004,09,输出路径/my_app/case/2004/09/
根据mytest_reverse别名解析里面的url解析规则,解析出固定的路径mytest/2003
urlpatterns = [
re_path(r"^case3/([0-9]{4,})/([0-9]{2})/$",case03,name = "mytest_reverse2"),
# 路径为my_app/case/2019/02/
path("mytest/2003",my_test,name="mytest_reverse")
#路径为my_app/mytest/2003
]
路由控制之名称空间
我们因为需要反向解析,在应用的分发器中会加入Name参数,以便反向解析动态获取一些数值
但是反向解析是根据name这个参数来的,不同的应用下name取值可能会重复,就会导致下面这个情况,my_app和my_app2下有相同的函数index,并且他们的命名都是name
所以my_app下的反向解析会被my_app2的反向解析覆盖,出现了运行各自应用下的index,但是反向解析出现了错误,所以我们需要把命名空间也按照不同的应用进行分隔.
按照应用分隔命名空间需要2步
第一:项目总路由那边include里面要添加元祖,参数一是按应用的分发路由,参数二是按应用定义的命名空间
第二:我们只需要后期reverse函数中使用命名空间:函数名
就可以在反向解析中获取正确的内容了
看正确的结果