Django 如何处理一个URL请求

2023-06-1017:31:57后端程序开发Comments828 views字数 3928阅读模式

当一个用户请求 Django 站点的一个页面,下面是 Django 系统决定执行哪个 Python 代码使用的算法:
1Django 确定使用根 URLconf 模块:通常,这是ROOT_URLCONF设置的值,但如果传入 HttpRequest 对象拥有urlconf属性(通过中间件设置),它的值将被用来代替ROOT_URLCONF设置
2Django 加载该 Python 模块并寻找可用的urlpatterns;它是django.urls.path()和(或)django.urls.re_path()实例的列表
3Django 会按顺序遍历每个urlpatterns然后会在所请求的 URL 匹配到第一个pattern 后停止,并与 path_info 匹配
4一旦有 URL 匹配成功,Djagno 导入并调用相关视图,视图可以是 Python 函数(或基于类的视图 class-based view )视图会获得如下参数:
○一个HttpRequest序列
○如果匹配的 URL 包含未命名组,那么来自正则表达式中的匹配项将作为位置参数提供
○关键字参数由路径表达式匹配的任何命名部分组成,并由django.urls.path()或django.urls.re_path()的可选 kwargs 参数中指定的任何参数覆盖
5如果没有 URL 被匹配,或者匹配过程中出现了异常,Django 会调用一个适当的错误处理视图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

简单的 URLconf文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

from django.urls import path
from . import views
urlpatterns = [
path('articles/2003/', views.special_case_2003),
path('articles/<int:year>/', views.year_archive),
path('articles/<int:year>/<int:month>/', views.month_archive),
path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail),
]

注意:
●要从 URL 中取值,使用尖括号
●捕获的值可以选择性地包含转换器类型比如,使用<int:name>来捕获整型参数如果不包含转换器,则会匹配除了 / 外的任何字符
●前面不需要添加反斜杠,因为每个 URL 都有,比如,应该是 articles 而不是 /articles文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

一些请求的例子
●/articles/2005/03/ 会匹配 URL 列表中的第三个,Django 会调用函数views.month_archive(request, year=2005, month=3)
●/articles/2003/ 将匹配列表中的第一个 pattern 不是第二个,因为 pattern 按顺序匹配,第一个会首先测试是否匹配;在这里 Django 会调用函数views.special_case_2003(request)
●/articles/2003不匹配任何一个 pattern ,因为每个 pattern 要求 URL 以一个斜线结尾
●/articles/2003/03/building-a-django-site/ 会匹配 URL 列表中的最后一项Django 会调用函数views.article_detail(request, year=2003, month=3, slug="building-a-django-site")文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

 文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

路径转换器
●str - 匹配除了 '/' 之外的非空字符串;如果表达式内不包含转换器,则会默认匹配字符串
●int - 匹配 0 或任何正整数返回一个 int
●slug - 匹配任意由 ASCII 字母或数字、-、_组成的短标签比如,building-your-1st-django-site
●uuid - 匹配一个格式化的 UUID ,为了防止多个 URL 映射到同一个页面,必须包含破折号并且字符都为小写比如075194d3-6885-417e-a8a8-6c931e272f00,函数参数会拿到一个 UUID 实例
●path - 匹配非空字段,包括路径分隔符 '/' ,它允许你匹配完整的 URL 路径而不是像 str 那样匹配 URL 的一部分文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

注册自定义的路径转换器
转换器是一个类,包含如下内容:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

regex 类属性
字符串形式的regex类属性文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

to_python(self, value)方法
●用来处理匹配的字符串转换为传递到函数的类型
●如果没有转换为给定的值,它应该会引发 ValueError
●ValueError 说明没有匹配成功,因此除非另一个 URL patterns 匹配成功,否则会返回 404文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

to_url(self, value)方法
●处理 Python 类型转换为字符串以用于 URL 中
●如果不能转换给定的值,它应该引发 ValueError
●ValueError 被解释为无匹配项,因此 reverse() 将引发 NoReverseMatch,除非有其他 URL patterns 匹配文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

class FourDigitYearConverter:    regex = '[0-9]{4}'
    def to_python(self, value):        return int(value)
    def to_url(self, value):        return '%04d' % value

在 URLconf 中使用register_converter()来注册自定义的转换器类:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

from django.urls import path, register_converter
from . import converters, views
register_converter(converters.FourDigitYearConverter, 'yyyy')
urlpatterns = [    path('articles/2003/', views.special_case_2003),    path('articles/<yyyy:year>/', views.year_archive),    ...]

使用正则表达式
●如果路径和转化器语法不能很好的定义 URL patterns ,可以使用正则表达式
●需要使用re_path()而不是path()
●在 Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中 name 是组名,pattern 是要匹配的 pattern文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

from django.urls import path, re_path
from . import views
urlpatterns = [    path('articles/2003/', views.special_case_2003),    re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),    re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.article_detail),]

这实现了与前面示例大致相同的功能,除了:
●将要匹配的 URLs 将稍受限制,比如,10000 年将不在匹配,因为 year 被限制长度为4
●无论正则表达式进行哪种匹配,每个捕获的参数都作为字符串类型发送到视图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

使用未命名的正则表达式组
●命名组语法,例如(?P<year>[0-9]{4})
●更短的未命名组,例如([0-9]{4})
不推荐这个用法,因为它会更容易在匹配的预期含义和视图参数之间引发错误,在任何情况下,推荐在给定的正则表达式里只使用一个样式
当混杂两种样式时,任何未命名的组都会被忽略,而且只有命名的组才会传递给视图函数
如果匹配的 URL 包含未命名组,那么来自正则表达式中的匹配项将作为位置参数提供文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

性能
urlpatterns 中的每个正则表达式在第一次访问它们时被编译,这使得系统相当快文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

URLconf 在什么上查找
请求的 URL 被看做是一个普通的 Python 字符串
URLconf 查找并匹配,进行匹配时将不包括 GET 或 POST请求方式的参数以及域名文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

https://www.example.com/myapp/ 请求中,URLconf 将查找 myapp/
在https://www.example.com/myapp/?page=3请求中,URLconf 仍将查找myapp/
URLconf 不检查使用了哪种请求方法;换句话讲,所有的请求方法 —— 即,对同一个URL的无论是 POST请求 、 GET请求 、或 HEAD 请求方法等等 —— 都将路由到相同的函数文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

指定视图参数的默认值文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

# URLconffrom django.urls import path
from . import views
urlpatterns = [    path('blog/', views.page),    path('blog/page<int:num>/', views.page),]
# View (in blog/views.py)def page(request, num=1):    # Output the appropriate page of blog entries, according to num.    ...

包含其它的URLconfs
两个 URL patterns 都指向了相同的视图函数views.page
第一个 pattern 不能在 URL 中捕获到任意东西,如果第一个 URL patterns 去匹配 URL,page() 函数会使用它默认参数 num=1
第二个 URL patterns 去匹配 URL,page() 函数都会使用捕获到的任何num值文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/46827.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/46827.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定