Django 如何处理请求
Django 通过将传入的 URL 路径路由到视图函数来处理请求。view 函数负责将响应返回给发出请求的客户端。不同的 URL 通常由不同的视图函数处理。要将请求路由到特定的视图函数,Django 会查看你的 URL 配置(或简称 URLconf)。默认项目模板定义 <myproject>/urls.py
中的 URLconf。
你的 URLconf 应该是一个 python 模块,它定义了一个名为 urlpatterns
的属性,该属性是 django.conf.urls.url()
实例的列表。每个 url()
实例必须至少定义一个正则表达式 (一个正则表达式)来匹配 URL,以及一个目标,它是一个视图函数或一个不同的 URLconf。如果 URL 模式以视图函数为目标,则最好为其命名,以便以后轻松引用该模式。
我们来看一个基本的例子:
# In <myproject>/urls.py
from django.conf.urls import url
from myapp.views import home, about, blog_detail
urlpatterns = [
url(r'^$', home, name='home'),
url(r'^about/$', about, name='about'),
url(r'^blog/(?P<id>\d+)/$', blog_detail, name='blog-detail'),
]
此 URLconf 定义了三种 URL 模式,所有这些模式都以视图为目标:home
,about
和 blog-detail
。
url(r'^$', home, name='home'),
正则表达式包含一个起始锚点’^’,紧接着是一个结束锚’$’。此模式将匹配 URL 路径为空字符串的请求,并将它们路由到 myapp.views
中定义的 home
视图。
url(r'^about/$', about, name='about'),
此正则表达式包含一个起始锚点,后跟文字字符串 about/
和结束锚点。这将匹配 URL /about/
并将其路由到 about
视图。由于每个非空 URL 都以/
开头,因此 Django 可以方便地为你剪切第一个斜杠。
url(r'^blog/(?P<id>\d+)/$', blog_detail, name='blog-detail'),
这个正则表达式有点复杂。它定义了起始锚点和文字字符串 blog/
,就像前面的模式一样。下一部分 (?P<id>\d+)
被称为捕获组。捕获组(如其名称所示)捕获字符串的一部分,Django 将捕获的字符串作为参数传递给视图函数。
捕获组的语法是 (?P<name>pattern)
。name
定义组的名称,这也是 Django 用于将参数传递给视图的名称。该模式定义了组匹配的字符。
在这种情况下,名称为 id
,因此函数 blog_detail
必须接受名为 id
的参数。模式是\d+
。\d
表示该模式仅匹配数字字符。+
表示模式必须匹配一个或多个字符。
一些常见的模式:
blog-detail
模式中的捕获组后面是文字/
和结束锚。
有效的网址包括:
/blog/1/ # passes id='1'
/blog/42/ # passes id='42'
例如,无效的网址是:
/blog/a/ # 'a' does not match '\d'
/blog// # no characters in the capturing group does not match '+'
Django 按照在 urlpatterns
中定义的相同顺序处理每个 URL 模式。如果多个模式可以匹配相同的 URL,这一点很重要。例如:
urlpatterns = [
url(r'blog/(?P<slug>[\w-]+)/$', blog_detail, name='blog-detail'),
url(r'blog/overview/$', blog_overview, name='blog-overview'),
]
在上面的 URLconf 中,第二个模式是不可访问的。该模式将匹配 URL /blog/overview/
,但不是调用 blog_overview
视图,URL 将首先匹配 blog-detail
模式并使用参数 slug='overview'
调用 blog_detail
视图。
为了确保 URL /blog/overview/
被路由到 blog_overview
视图,模式应该放在 blog-detail
模式之上:
urlpatterns = [
url(r'blog/overview/$', blog_overview, name='blog-overview'),
url(r'blog/(?P<slug>[\w-]+)/$', blog_detail, name='blog-detail'),
]