在django中所有的路由最终都会保存在一个叫urlpatterns
中,urlpatterns必须声明在主应用下的url.py总路由中,这是由配置文件settings中的ROOT_URLCONF = '主应用名称.urls'
配置的。
这里的配置当然可以进行修改,但是必须确保修改后的路径文件内存在urlpatterns
变量,而且必须是列表类型。
在django运行中,当客户端发送了一个http请求到服务端,服务端的web服务器则会从http协议中提取url地址,从程序内部找到项目中添加到urlpatterns里面的所有路由信息的url进行遍历匹配。
如果相等或者匹配成功,则调用当前url对应的视图方法。
在给urlpatterns路由列表添加路由的过程中,django一共提供了两个函数给开发者注册路由
from django.urls import path # 普通路由
from django.urls import re_path # 正则路由,会把url地址看成一个正则模式与客户端的请求url地址进行正则匹配
# path和re_path 使用参数一致,仅仅在url参数和接收参数时写法不一样
一、path路由注册
从绑定路由的执行上效率,使用path比re_path的效率高很多,因为path默认情况下仅仅是通过字符串比较,而re_path是使用正则匹配
# pat("路由url", 视图函数, name="路由别名")
path("index.html4", view.index4, name="index4")
二、re_path路由注册
视图函数
def profile(request, pk):
print(pk)
return HttpResponse('获取用户信息')
路由映射关系
from django.urls import path, re_path
urlpatterns = [
# ....
re_path('^profile/(?P[0-9]+)/$' , views.profile),
]
注:
-
首先要导入re_path
from django.urls import path, re_path
-
^
与$
分别表示正则的开始于结束 -
(?P
一个匹配表达式[0-9]+) ()
表示一个正则表达式的匹配关系?P
表示后面的匹配规则对应的参数是pk参数[0-9]
表示匹配0-9之间的数字+
表示可匹配多个
改造视图函数:
def profile(request, pk, mobile):
print(pk)
print(mobile)
return HttpResponse('获取用户信息')
改造urls
from django.urls import path, re_path
urlpatterns = [
# ....
re_path('^profile/(?P[0-9]+)/mobile/(?P1[3-9]\d{9})/$' , views.profile),
]
注:
- 此时就表示需要两个参数,pk及mobile
(?P
表示匹配一个手机号1[3-9]\d{9}) ?P
表示匹配的对应参数是mobile1
表示匹配1[3-9]
表示匹配3-9之间的任意数字一次\d{9}
表示匹配任意数字九次
- 请求示例:
host:port/profile/513/mobile/13112312311
- 那么请求到达视图函数后pk接收到了513,mobile接收到了13112312311
- 需要注意的是,参数到达视图函数后,参数接收到的类型都是str类型
TODO:更多正则相关可自行了解,也可对re模块进行自我学习
三、Django的url路由加斜杠的问题
在django路由中编写url地址时,为了快速查找,简易最好不在路由的后面加上
/
,当用户访问对应视图的路由时,加不加斜杠,Django都能转换到正确的url地址,这个方式虽然好,但是会导致我们客户端的静态文件的url路径如果是相对路径,则会被Django这个做法导致出现路径正确的情况,所以不要加斜杠。
当然,如果我们编写的是属于前后端分离的项目的话,加不加斜杠不存在影响。
四、路由转换器
路由转换器也叫路由验证器,有两个作用:
- 把路由参数进行类型转换
- 验证路由匹配
官方文档
下面的路径转换器在默认情况下是有效的:
str
- 匹配除了'/'
之外的非空字符串。如果表达式内不包含转换器,则会默认匹配字符串。
int
- 匹配 0 或任何正整数。返回一个
int
。slug
- 匹配任意由 ASCII 字母或数字以及连字符和下划线组成的短标签。比如,
building-your-1st-django-site
。uuid
- 匹配一个格式化的 UUID 。为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写。
比如,
075194d3-6885-417e-a8a8-6c931e272f00
。返回一个
UUID
实例。path
- 匹配非空字段,包括路径分隔符'/'
。它允许你匹配完整的 URL 路径而不是像
str
那样匹配 URL 的一部分。
示例:
视图函数:
def demo1(request, num):
print(num, type(num))
return HttpResponse('ok')
urls:
urlpatterns = [
# 路由转换器
path('demo1/' , views.demo1),
]
注:
- 此时视图函数接收到的num就不是str类型了,而是int类型
就是路由转换器的写法int
表示转换器类型是int类型num
对应着视图函数中的形参名称,传递到视图函数时就将值传递给num参数
对于更复杂的匹配需求,你能定义你自己的路径转换器。
转换器是一个类,包含如下内容:
- 字符串形式的
regex
类属性。 to_python(self, value)
方法,用来处理匹配的字符串转换为传递到函数的类型。如果没有转换为给定的值,它应该会引发
ValueError
。ValueError
说明没有匹配成功,因此除非另一个 URL 模式匹配成功,否则会向用户发送404响应。- 一个
to_url(self, value)
方法,它将处理 Python 类型转换为字符串以用于 URL 中。如果不能转换给定的值,它应该引发
ValueError
。ValueError
被解释为无匹配项,因此reverse()
将引发NoReverseMatch
,除非有其他 URL 模式匹配。
可以参考内置转换器的写法,内置转换器所在位置:\应用名称\Lib\site-packages\django\urls\converters.py
示例:
在user子应用下新建converters.py
文件
from django.urls.converters import StringConverter, register_converter
# Custom URL Converters
# 一般会继承StringConverter,并且重写to_python方法
# to_python方法会接收一个参数,这个参数就是url中的参数,其作用是将url中的参数转换为python中的参数
# to_url方法会接收一个参数,这个参数就是python中的参数,其作用是将python中的参数转换为url中的参数
class MobileConverter(StringConverter):
regex = r'^\+?1?\d{9,15}$'
# Register the converters
register_converter(MobileConverter, 'mobile')
视图函数
def demo2(request, mobile):
print(mobile)
return HttpResponse('ok')
urls
from django.urls import path
from user import views
# 导入自定义的路由转换器
from user.converters import MobileConverter
urlpatterns = [
# 自定义路由转换器
path('demo2/' , views.demo2),
]
注意:
-
自定义路由转换器,实际上就是django在对路由进行数据转换和简写正则路由的实现,这种实现方式是基于不同的转换器类来完成,开发者要实现自定义转换器,需要编写的类必须符合官方要求的3个基本要求:
- 必须声明属性:regex
- 必须声明的方法:
- to_python
- to_url
- 必须以类格式编写
- 必须通过register_converter()进行注册才能被调用
-
这种实现方式,实际就是对编程领域的设计模式的一种应用,设计模式,前任总结下来的基于固定业务场景的解决方案就是设计模式,编程中,设计模式有23种不同设计模式,其中,我们上面这种就是叫策略模式/接口模式
-
一般在工作中,往往可以使用策略模式来进行营销活动(优惠券、打折)的实现
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)