URL调度器
当一个用户请求 Django 站点的一个页面,下面是 Django 系统决定执行哪个 Python 代码使用的算法:
基本介绍
当一个用户请求 Django 站点的一个页面,下面是 Django 系统决定执行哪个 Python 代码使用的算法:
- Django 确定要使用的根 URLconf 模块,一般是在 settings 中的 ROOT_URLCONF 设置的值,但是如果传入 HttpRequest 对象具有一个 urlconf 属性(由中间件设置),则其值将用于代替 ROOT_URLCONF 设置。
- Django 加载该 URLconf 模块并查找变量 urlpatterns,它是一个列表 django.urls.path() 和 / 或 django.urls.re_path()实例。
- Django 按顺序遍历每个 URL 模式,并停在与请求的 URL 匹配的第一个 URL 模式,需要特别注意编写的顺序
- 一旦某个 URL 模式匹配,Django 就会导入并调用给定的视图,该视图是一个简单的 Python 函数(或基于类的视图方法)。该视图通过以下参数传递:
- 一个 HttpRequest 实例。
- 如果匹配的 URL 模式没有返回任何命名组,则来自正则表达式的匹配作为位置参数提供。
- 关键字参数由路径表达式匹配的任何命名部分组成,并由可选的 kwargs 参数传给 django.urls.path()或 django.urls.re_path()。
- 如果没有 URL 模式匹配,或者在此过程中的任何点发生异常,Django 将调用适当的错误处理视图
基本使用
- 修改主应用下的
urls.py
文件
from django.contrib import admin
from django.urls import path
from modules.login.views import (
loginFunc,
loginFunc1,
loginFunc2,
loginFunc3,
)
from modules.user.views import userFunc
urlpatterns = [
path("admin/", admin.site.urls),
path("user/", userFunc),
path("login/", loginFunc), # 普通
path("login/test/", loginFunc1), # 可以多个斜杠
path("login/<id>/'", loginFunc2), # 传递一个名为id的参数
path("login/str/<int:id>/", loginFunc3), # 规定传递参数的类型
]
- 业务逻辑的书写
from django.http import HttpResponse
def loginFunc(request):
return HttpResponse("login")
def loginFunc1(request):
return HttpResponse("login/test")
def loginFunc2(request, id):
return HttpResponse("login/" + id)
def loginFunc3(request, id):
return HttpResponse("login/只能是数字" + str(id))
此时分别访问:
http://localhost:8000/login/
http://localhost:8000/login/test/
http://localhost:8000/login/1/ http://localhost:8000/login/a/
路径转换器
str
:匹配任何非空字符串,不包括路径分隔符'/'。如果转换器不包含在表达式中,这是默认值。int
:匹配零或任何正整数。返回一个 int。slug
:匹配由 ASCII 字母或数字组成的字符串,以及横线和下划线字符。例如: building-your-1st-djangosite 可以匹配,django@site 是不可以匹配的。uuid
:匹配格式化的 UUID。为防止多个 URL 映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID 实例。path
:匹配任何非空字符串,包括路径分隔符 '/',可以匹配完整的 URL 路径,而不仅仅是 URL 路径的一部分 str,使用时要谨慎,因为可能造成后续的所有 url 匹配都失效。
自定义转换器
转换器是一个包含以下内容的类:
- 一个 regex 类属性,作为一个 re 匹配字符串
- to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型
- to_url(self, value)方法,用于处理将 Python 类型转换为 URL 中使用的字符串
自定义方式如下:
在视图同级文件夹下新建一个
converters.py
文件,在文件中定义一个 FourDigitYearConverter 类:class FourDigitYearConverter(object): regex = '[0-9]{4}' # 0-9的数字出现4次就能匹配上 def to_python(self, value): return int(value) def to_url(self, value): return '%04d'+'哈啊哈' % value
使用 register_converter()方法在 URLconf 中注册自定义转换器类 :
from django.contrib import admin from django.urls import path from login import views # 注册自定义转换器 from django.urls import register_converter from login.converters import FourDigitYearConverter register_converter(FourDigitYearConverter, 'yyyy') # 随便起个名字 urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.loginFunc), # 普通 path('login1/<yyyy:id>/', views.loginFunc1), # 自定义转换器(类型) ]
此时,我们访问:http://127.0.0.1:8000/login1/1234/ 和 http://127.0.0.1:8000/login1/5478/
分别看到了 login/1234 和 login/5678
默认值和额外参数
默认值
url 配置
from django.contrib import admin
from django.urls import path
from modules.login.views import (
loginFunc1,
)
urlpatterns = [
path("admin/", admin.site.urls),
path("login/", loginFunc1),
path("login/<int:page>/", loginFunc1),
]
业务处理
from django.http import HttpResponse
def loginFunc1(request, page=10):
return HttpResponse(f"返回第{page}页的数据")
此时,分别访问: http://127.0.0.1:8000/login/ 和 http://127.0.0.1:8000/login/22/
额外参数
url 配置
from django.contrib import admin
from django.urls import path
from modules.login.views import (
loginFunc1,
)
urlpatterns = [
path("admin/", admin.site.urls),
path("login/", loginFunc1, {"name": "lcl"}),
]
业务处理
from django.http import HttpResponse
def loginFunc1(request,name):
return HttpResponse(f"返回{name}的数据")
此时,访问: http://127.0.0.1:8000/login/
自定义错误页面
在 settings 中修改配置:
DEBUG = False
ALLOWED_HOSTS = ['*']
在主应用的 urls 中配置:
from django.contrib import admin
from django.urls import path
from modules.login.views import (
loginFunc1,
)
urlpatterns = [
path("admin/", admin.site.urls),
path("login/", loginFunc1),
# path("login/", loginFunc1, {"name": "lcl"}),
]
handler404 = "modules.login.views.loginFunc2"
handler500 = "modules.login.views.loginFunc3"
错误页面逻辑
from django.http import HttpResponse
def loginFunc1(request, name):
return HttpResponse(f"返回{name}的数据")
def loginFunc2(request, exception):
return HttpResponse("404错误页面")
def loginFunc3(request):
return HttpResponse("500错误页面")
此时,去访问:http://127.0.0.1:8000/login123/ 就会进入 404 错误页面,访问:http://127.0.0.1:8000/login/ 就会进入 500 错误页面
引用其他 URL 调度器
每个子应用下都会拥有自己的 urls.py 文件,合理的方式是在各自的 urls.py 下进行路由配置,之后在主应用下进行导入
- 子应用的 urls
modules.login.urls
from django.urls import path
from modules.login.views import (
loginFunc1,
loginFunc2,
loginFunc3,
)
urlpatterns = [
path("func1/", loginFunc1, {"name": "lcl"}),
path("func2/", loginFunc2),
path("func3/", loginFunc3),
]
- 主应用的 urls
djangostudy.urls
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("login/", include("modules.login.urls")),
]
业务逻辑处理
from django.http import HttpResponse
def loginFunc1(request, name):
return HttpResponse(f"返回{name}的数据")
def loginFunc2(request):
return HttpResponse("func2")
def loginFunc3(request):
return HttpResponse("func3")