第十章 Django的路由
-
URL配置(URLconf)就像是Django所支撑网站的目录。
-
它的本质是URL与要为该URL调用的视图函数之间的映射表。
-
我们就是以这种方式告诉Django,遇到哪个URL的时候,要对应执行哪个函数。
10.1.2 Django处理请求
-
Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONF setting, but if the incoming HttpRequest object has a urlconf attribute (set by middleware), its value will be used in place of the ROOT_URLCONF setting。
-
Django loads that Python module and looks for the variable
urlpatterns
. This should be a Python list of django.conf.urls.url() instances. # 返回一个对象 -
Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.
-
Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function (or a class-based view). The view gets passed the following arguments:
-
An instance of HttpRequest.
-
If the matched regular expression returned no named groups, then the matches from the regular expression are provided as positional arguments.
-
The keyword arguments are made up of any named groups matched by the regular expression, overridden by any arguments specified in the optional
kwargs
argument to django.conf.urls.url().
-
-
If no regex matches, or if an exception is raised during any point in this process, Django invokes an appropriate error-handling view. See Error handling below.
10.2. 基本格式
from django.conf.urls import url urlpatterns = [ url(正则表达式, views视图,参数,别名), ]
- 示例
from django.conf.urls import url from . import views urlpatterns = [ # 静态路由 url(r'^articles/2003/$', views.special_case_2003), # 动态路由 url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ]
10.2.1 Django 1.11参数
-
正则表达式:一个正则表达式字符串
-
views视图:一个可调用对象,通常为一个视图函数
-
参数:可选的要传递给视图函数的默认参数(字典形式)
-
别名:一个可选的name参数
from django.urls import path,re_path 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), ]
- 2.0版本中re_path和1.11版本的url是一样的用法。
10.3. 正则表达式
10.3.1 注意事项(4)
-
urlpatterns中的元素按照书写顺序从上往下逐一匹配正则表达式,一旦匹配成功则不再继续。
-
若要从URL中捕获一个值,只需要在它周围放置一对圆括号(分组匹配)。
-
不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
-
每个正则表达式前面的'r' 是可选的但是建议加上。
-
APPEND_SLASH = True
10.3.2 分组
-
位置传参
-
urls.py中的正则表达式分组匹配(通过圆括号)来捕获URL中的值并以位置参数形式传递给视图。
from django.conf.urls import url from . import views urlpatterns = [ url(r'^bolg/([0-9]{4})/(\d{2})', views.blog), ]
# URL: /bolg/2008/08 def blog(request, year, month): return HttpResponse('ok') # 调用方式 blog(request, '2008', '08')
10.3.3 分组命名匹配
-
关键字传参
-
from django.conf.urls import url from . import views urlpatterns = [ url(r'^bolg/(?P<year>[0-9]{4})/(?P<month>\d{2})', views.blog), ]
# URL: /bolg/2008/08 def blog(request, year, month): return HttpResponse('ok') # 调用方式 blog(request, year='2008', month='08')
-
URLconf 不检查请求的方法。
-
换句话讲,所有的请求方法,同一个URL的POST、GET、HEAD等等,都将路由到相同的函数。
-
每个在URLconf中捕获的参数都作为一个普通的Python字符串传递给视图,无论正则表达式使用的是什么匹配方式。
-
可以为关键字传参的view函数,指定默认值,应用于分页
10.4. include()方法
参数:
-
urls.py 的导入,如'app.urls'
-
namespace='app'
10.4.1 基本使用
-
主要作用是进行路由的二级分发
-
导入include,from django.conf.urls import include
# At any point, your urlpatterns can “include” other URLconf modules. This essentially “roots” a set of URLs below other ones. # For example, here’s an excerpt of the URLconf for the Django website itself. It includes a number of other URLconfs from django.conf.urls import include, url urlpatterns = [ url(r'^admin/', admin.site.urls), # 可以包含其他的URLconfs文件,路由分发 url(r'^blog/', include('blog.urls')), ]
10.4.2 传递额外参数
-
如果命名分组名和传参名相同则优先选择,关键字传参的值
-
# app(bolg)内的urls.py from django.conf.urls import url from . import views urlpatterns = [ # 传递关键字参数给视图,类型为字典中的type。优先级比命名分组优先级要高 url(r'^blog/', views.blog, {'year': 2008}), ]
-
settings.py中的ROOT_URLCONFG='xxx.urls',表示核心路由起始位置,可根据需求进行更改
10.4.3 命名url和url反向解析
-
在使用Django 项目时,一个常见的需求是获得URL的最终形式,以用于嵌入到生成的内容中(视图中和显示给用户的URL等)或者用于处理服务器端的导航(重定向等)。
-
命名url和url反向解析,就是一个DRY(Don't repeat yourself) 机制。
-
解决硬编码不灵活的问题。
1. 命名url
url(r'^blog/', views.blog, {'year': 2008}, name='blog'),
-
通过命名生成url路径的完整路径
-
{# 获取的是完整的url路径,string类型 #} {% url 'blog' %}
- 获取完整到 url 路径,通过name进行反向解析,即通过urls.py获取
# views.py # 也可以通过django.shortcuts 导入 from django.urls import reverse url = reverse('blog')
3. 分组
url(r'^bolg/([0-9]{4})/(\d{2})', views.blog, name='blog'),
- py文件中使用
# py文件, args为tuple 推荐最后一个参数加 , url = reverse('blog', args=('2008', '08',))
- 模版中使用
{# 使用 #} {% url 'blog' 2011 12 %}
4. 命名分组
-
urls.py文件中配置
-
使用时,
url(r'^bolg/(?P<year>[0-9]{4})/(?P<month>\d{2})', views.blog, name='blog')
- py文件中使用
# 在py文件中使用, args为tuple 推荐最后一个参数加 , url = reverse('blog', args=('2008', '08',)) url = reverse('blog', kwargs={'year': '2008', 'month': '08'})
- 模版中使用
{# 在模版中使用 #} {% url 'blog' 2011 12 %} {% url 'blog' year=2011 month=12 %}
5. namespace
-
命名空间,
url(r'^app01/', include('app01.urls'), namespace='app01') url(r'^app02/', include('app02.urls'), namespace='app02')
-
-
name通常加在 app下的urls.py文件中的url
-
namespace可以进行多级嵌套 使用冒号 :
{% url 'namespace值:blog' %} {% url 'app01:blog' %} {% url 'app02:blog' %}
url = reverse('app01:blog')