Django如何处理请求

示例

Django通过将传入的URL路径路由到视图函数来处理请求。视图功能负责将响应返回给发出请求的客户端。不同的URL通常由不同的视图功能处理。要将请求路由到特定的视图功能,Django会查看您的URL配置(或简称URLconf)。默认项目模板在中定义URLconf <myproject>/urls.py。

您的URLconf应该是一个python模块,该模块定义了名为的属性urlpatterns,该属性是实例的列表。每个实例至少必须定义一个正则表达式(正则表达式)以与URL匹配,并定义一个目标,该目标可以是视图函数或不同的URLconf。如果URL模式以视图函数为目标,则最好给它起一个名称,以便以后轻松引用该模式。django.conf.urls.url()url()

让我们看一个基本的例子:

# In <myproject>/urls.py

from django.conf.urls import url

frommyapp.viewsimport 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'),

正则表达式包含一个开始锚“ ^”,紧随其后是一个结束锚“ $”。该模式将匹配网址路径为空字符串的请求,并将其路由到中home定义的视图myapp.views。

  • 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将捕获的字符串作为参数传递给view函数。

捕获组的语法为(?P<name>pattern)。name定义组的名称,这也是Django用于将参数传递给视图的名称。该模式定义该组匹配哪些字符。

在这种情况下,名称为id,因此该函数blog_detail必须接受名为的参数id。模式是\d+。\d表示该模式仅与数字字符匹配。+表示模式必须匹配一个或多个字符。

一些常见的模式:

模式用于火柴
\d+ID一个或多个数字字符
[\w-]+sl一个或多个字母数字字符,下划线或破折号
[0-9]{4}年(长)四个数字,从零到九
[0-9]{2}今年(短)

月的一天
两个数字,从零到九
[^/]+路径段除斜杠外的所有内容

模式中的捕获组blog-detail后跟一个literal/和结尾锚。

有效的URL包括:

  • /blog/1/ # passes id='1'

  • /blog/42/ # passes id='42'

无效的URL例如:

  • /blog/a/ # 'a' does not match '\d'

  • /blog// # no characters in the capturing group does not match '+'


Django按照在中定义的相同顺序处理每个URL模式urlpatterns。如果多个模式可以匹配同一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_overviewURL会首先与该blog-detail模式匹配并blog_detail使用参数调用视图,而不是调用视图slug='overview'。

为确保将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'),
]