一、URL路由配置的用途
URL
是Django
收到用户请求后,根据用户请求的URL
地址和urls.py
里配置的映射关系,以正确的确定出某个URL
调用哪一段逻辑代码来对应执行相应的视图函数或视图类,最后由视图返回给客户端想要接收的数据。
简单的例子:
from django.urls import path
urlpatterns = [
path('index', views.index),
]
# index这个路由对应着视图函数中index这个方法,浏览器输入这个链接,就会响应到index这个函数来执行
二、URL配置的位置与方法
2.1 URL配置的位置
- 项目目录中的
urls.py
,通常情况下当应用仅有一个的时候只在此位置配置即可 - 应用目录中的
urls.py
,当应用大于2个时,会导致项目目录下urls.py
中配置过多,且难以区分是哪个应用对应的URL
,这时需要在项目目录urls.py
中配置进行路由分发,各应用下创建一个名为urls.py
文件,然后配置各应用下的URL
,以将不同应用的URL
配置隔离开来
2.2 URL配置的方法
- Django1.x版本中(现在几乎不用)
from django.conf.urls import url
from app_name import views
urlpatterns = [
url(正则表达式, views视图函数,参数,别名),
url(r'^blog/$', views.blog), # 例子
]
- Django2.x和3.x版本中(path为主)
# re_path就是一个具有正则表达式功能的路径
from django.urls import path,re_path,include
from app_name import views
from django.contrib import admin
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r"^articles/2003/$",views.special_case_2003), # 正则,只能是字符串
path("articles/<int:month>",views.month), # path转换器,可以转换格式
path("app01",include(app01.urls))
]
三、settings.py中的URL配置
- APPEND_SLASH:
Django settings.py
配置文件中默认没有APPEND_SLASH
这个参数,但Django
中默认这个参数为True
, 其作用就是自动在网址结尾加/
,由django.middleware.common.CommonMiddleware
这个中间件来实现的
# 是否开启URL访问地址后面不为/跳转至带有/的路径的配置项
APPEND_SLASH=True
四、URL路由配置之有名分组(re_path)
Python
函数传参时一般是通过位置传参,这种方式可能会导致我们在编写视图中出现一些错误,因此需要使用Python的关键字传参的方法来对其进行传参,这样就不会因为参数的位置而导致错误的发生。这种URL配置好处就是没有位置紊乱的问题,但是需要注意的是,视图里面只能是<name>
里面的name
,不能换为其它名称。
# re_path就是一个具有正则表达式功能的路径
from django.urls import path,re_path
from app01 import views
urlpatterns = [
# 此方式只能是year_month(request,y=year,m=month),才能保证正确传参
re_path(r"^articles/([0-9]{4})/([0-9]{2})/$",views.year_month),
# year_month(request,y=year,m=month)或者year_month(request,m=month,y=year)都可以
re_path(r"^articles/(?p<year>[0-9]{4})/(?p<month>[0-9]{2})/$",views.year_month),
]
五、URL路由配置之path转换器
5.1 path内置转换器介绍
rlpatterns = [
re_path("^articls/(?p<articls_id>[0-9]{4})/detail$",views.detail)
re_path("^articls/(?p<articls_id>[0-9]{4})/edit$",views.edit)
re_path("^articls/(?p<articls_id>[0-9]{4})/delete$",views.delete)
]
问题的提出:
- 前面
re_path
所传输的其实都是字符串,字符类型能否自动转换以便于我们使用呢 - 以上
urlpatterns
中后三个url
中有相同的正则,是否能够只修改一处正则即可实现不同的url
,而避免因正则发生变化而做重复性的工作呢
path
使用的基本规则
- 使用
<>
从url
中捕获值,无需在前面添加前导斜杠/
- 捕获值可以包含一个转化器类型
convert type
,如<int:name>
捕获到整数变量,也属于有名分组 - 如果不使用转换器,将会匹配到任何字符串,也包括
/
转换器类型 | 类型说明 |
---|---|
<int:number> | 将number 转换为整型,匹配0 或任何正整数 |
<str:name> | 将name 转换为浮点型,匹配除了/ 之外的非空字符 |
<slug:path1> | 匹配字母、数字、下划线组成的字符串 |
<uuid:path2> | 匹配格式化的UUID唯一识别码 |
<path:path3> | 匹配任何非空字符,包括路径分割符,? 除外 |
5.2 自定义path内置转换器
- 和前面应用中
urls.py
类似,新建一个py
文件来保存
# 比如新建一个urlconvert.py于app01中
class MonthConvert:
# 需要设定的正则表达式
regex = "[0-9]{2}" # 这是一个属性命名,这里不能更改,只能是这样
def to_python(self,value):
"""用于url设定的内置转换器"""
return int(value)
def to_url(self,value):
"""用于url反向解析"""
return '%04d' % value
- 然后通过
register_converter
进行注册
from django.urls import register_convert
# 将之前所写的类也加进来
from app01.urlconvert import MonthConvert
register_convert(MonthConvert,"mm") # "mm"是一个标记
5.3 path转换器的使用
urlpatterns = [
re_path("articles/(?p<m>[0-9]{2})",views.month)
path("articles/<int:month>",views.month),
path("articles/<mm:month>",views.month),
]
- 以上三种方式对应的路径是相同的,不同之处在于后两个返回的都是
int
,前面是str
- 可通过
int(m)
将其转换一下,此时则相同了
六、URL控制之反向解析
- 其目的就是防止路径写死,使URL的使用变得更加灵活,从而不利于开发者维护
- 通过在urls.py配置URL时添加一个别名name=“val”,注意val保证唯一性,然后可以利用name值来进行反向解析出配置的URL
6.1 模板中URL的反向解析
- 创建一个
login.html
- 创建一个
login
视图- 通过
get
与post
来进行判断与验证 get
请求用于显示login.html
,post
请求用于验证,跳转至其它页面,在Django
中通过request.method
来查看请求方法
- 通过
# django项目中的settings.py需要注释掉这一行,这是一个跨站请求的组件,
# 如果不注释掉会报一些错误,也可以通过在模板中加入csrf-token的模板标签和视图中加入装饰器避免错误
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# file:login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="{% url "Log" %}" method="post">
用户名:<input type="text" name="user">
密码:<input type="password" name="pwd">
<input type="submit">
</form>
</body>
</html>
{% naeme %}
是专用于渲染html
标签的,{% url "name" %}
专用于URL
的反向解析,在具体的URL
配置中添加name
来实现,如下面代码所示,通过另起一个名为Log
来作为匹配的路径变量,从而将此路径放入form
表单的action
中。这里的name
相当于前端里面的id、class
的功能类似- 浏览器渲染此页面时,会将
name
所标记的url
通过Django
的模板语法自动渲染到模板里面
# app01的urls.py中的配置文件
# re_path就是一个具有正则表达式功能的路径
from django.urls import path, re_path
from app01 import views
urlpatterns = [
path(r"login.html/",views.login,name="Log"),
]
# file app01/views.py
def login(request):
# request.method用于查看是get请求还是post请求
if request.method == "GET":
return render(request,"login.html")
elif:
# request.GET获取GET请求的内容
# request.POST获取POST请求的内容
# 他们的结果都是一个Python字典,则可以通过get("name")来进行取值
user = request.POST.get("user")
pwd = request.POST.get("pwd")
if user=="qinhao" and pwd=="123456":
return HttpResponse("登录成功")
else:
return HttpResponse("用户名或密码错误")
- 此时的逻辑如下所述:
- ① 用户首先通过输入网址,从而通过
url
匹配到login
这个视图函数 - ② 匹配到这个函数后,通过判断请求方式是
GET
还是POST
请求 - ③ 用户第一次访问是通过
GET
请求进去到login.html
这个视图页面的,当用户输入用户名和密码后点击提交,此时即触发了一个POST
请求,通过{% url "Log" %}
模板语法将form
中action
的URL
自动更换为login.html/
,最后提交表单又跳转至login
这个视图 - ④ 此时的请求为
POST
请求,然后通过验证登录名与密码,从而实现用户的登录验证
- ① 用户首先通过输入网址,从而通过
6.2 视图函数中URL的反向解析
# 从url中调用
from django.urls import reverse
...
# url = reverse(name) name就是你在url所写的标签名,通过reverse即可进行url的反向解析
url = reverse("S_C_2003")
# 必须要满足url的正则规定,否则方向解析就会失败的出现错误,
# 有几个正则就需要传入几个参数以元组的方式进行传输
url = reverse("year",args=(3333,))
...
6.2.1 URL无正则的反向解析
# 在URL中添加name
urlpatterns = [
path('timer/', views.timer),
# 路由配置: 路径 ---->> 视图函数
# ^表示必须以什么开头;$表示必须以什么结尾
re_path(r"^articles/2003/$",views.special_case_2003,name="S_C_2003"),
# ()表示分组有几个就表示有几个组并且需要多传入分组数的参数,
# [0-9]表示任意的0-9,{4}表示有四个[0-9]
re_path(r"^articles/([0-9]{4})/$",views.year,name="year"),
path(r"login.html/",views.login,name="Log"),
]
# 从url中调用
from django.urls import reverse
from django.shortcuts import render,HttpResponse
def login(request):
# url = reverse(name) name就是你在url所写的标签名,
# 通过reverse即可进行url的反向解析
url = reverse("S_C_2003")
print(url)
return HttpResponse("HELLO")
6.2.2 URL有正则的反向解析
# 基于上面的url,有一个正则表达式,这里就需要传入一个元组的参数才能完成这次的方向解析
# 并且必须要满足url的正则规定,否则方向解析就会失败的
from django.urls import reverse
from django.shortcuts import render,HttpResponse
def login(request):
# url = reverse(name) name就是你在url所写的标签名,通过reverse即可进行url的反向解析
# 有几个正则就需要传入几个参数以元组的方式进行传输
url = reverse("year",args=(3333,))
print(url)
return HttpResponse("HELLO")
七、URL之路由分发
-
应用于应用较多时,路由配置也就变的十分繁琐,不能有效方便的进行管理
-
路由分发的目的就是一个应用在全局的
urls.py
中对应一个path
-
Django
中,主路由配置文件urls.py
可以不处理用户具体路由,主路由配置文件的可以做一个请求的分发(即分布式请求处理)。具体的请求可以由各应用进行处理:
7.1 在主路由中调用include函数
- 语法:
include(“appname.urls”)
- 作用:用于将当前路由转到各个应用的路由配置文件的
urlpatterns
进行分布式处理。 - 用于不同
app
(应用)中的name
值一样时,避免name
值相同而导致路径拦截或覆盖,造成所渲染的内容出错。通过在app01
与app02
中设置urls
中添加name
的后面,在添加一个namespace
从而区分name
。
# 在总项目中的urls.py中设置一个namespace
from django.urls import path,re_path,include
urlpatterns = [
# app01是一个命名空间,include是以一个元组传输的,第一参数是
re_path(r"^app01/",include(("app01.urls","app01"))),
re_path(r"^app02/",include(("app02.urls","app02"))),
]
# 并在reverse函数中通过
reverse("app01:name")
# 这里的app01就是命名空间,相当于通过指定一个房子里面对应的房间号
注意:
- 当我们使用命名空间时,无论是在哪儿,反向解析时我们都应该变为
namespace:name
这种格式 - 如前面form表单里的模板就应该替换为
% url "app01:Log"%}
namespace
是不能够有重复的,一般就用app_name
即可
7.1 在应用下配置urls.py
- 在应用下手动创建
urls.py
文件
from django.urls import math
from . import views # 此时与views.py为同级目录
# app01应用下
urlpatterns = [
# https://127.0.0.1:8000/app01/index
path("index/",views.index,name="AA"),
]