Django的URLconf
一. 为了将URL和视图关联起来,Django使用了’URLconfs’来配置,URLconf将URL模式映射到视图。
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),
]
这里使用<int:year>
,目的是从url里面获取到value值。
二. Path converters
- str---------可以匹配任何非空的字符串
- int---------匹配到非负整数(0以及正整数),返回int类型
- slug-------匹配slug string(比如building-your-1st-django-site就是slug string,slug string是为了解决url上面不能出现空格,所以在每个单词中间用横杠-代替空格。)
- uuid-------匹配正式的uuid. 为了防止访问多个url都跳转到同一个网页,所以使用到uuid,唯一性而且数量还很多。一个uuid必须有短横杠,而且英语字母必须是 小写的,比如075194d3-6885-417e-a8a8-6c931e272f00是uuid, 返回UUID实例。
- path------匹配非空的字段,包括分隔线/。
三. 注册自定义的path converter(路径转化器)
对于很复杂的对应要求,可以自己定义自己的path converter.
(一)对于一个path converter, 它是一个类,包含以下的东西:
- 一个正则属性,类型是字符串类型
- 一个to_python(self, value)方法,这个方法目的转换类型,把匹配的字符串转换成你想要的类型,然后将转换后的这个值传递到视图中去。
- 一个to_url(self, value)方法,它的作用是把一个Python类型转换成字符串类型应用到url中
如下所示:
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()
进行注册自定义的converter类
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('article/<yyyy:year>', views.year_archive),
...
]
四. 使用正则表达式
when the path and converters syntax isn’t sufficient for defining your URL patterns, you can also use regular expressions. to do so, use re_path() instead of path()
如果url使用正则匹配,那在URLconf里面就用re_path
来代替path
. please keep the following regualtions in mind.
- the syntax for named regular expression groups is (?Ppattern), name是组名, and pattern is some pattern to match.
- each captured argument is sent to the view as a string, regardless of what sort of match the regular expression makes(正则匹配到的字段不管是什么类型,传递给view视图去都是字符串类型)
- 使用正则表达式的规则时候,pattern group也可以不命名:
([0-9]{4})
,但是这种shorter unnamed group的方式是不推荐的,因为会很容易引入错误,当named group和unmamed group同时存在的时候,unnamed group会被忽视从而不会被传入到视图中去。 - 正则表达式支持nested arguments. nested arguments的意思就是说:在匹配URL的时候,正则规则需要使用到这个参数,但是在view里面并不需要这个参数,所以不把这个参数传递给view,可以使用
?:
来进行忽略。请看示例二;
(一)示例一:named group regular expression
from django.urls import path, re_path
from . import views
urlpattern = [
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),
]
(二)示例二:nested argument
from django.urls import re_path
urlpatterns = [
re_path(r'^blog/(page-(\d+)/)?$', blog_articles), # bad
re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), # good
]
假如url使用blog/page-2
, 匹配到blog_articles时,会传递两个参数到views视图,page-2/
和2
。
第二个匹配到comments时候,会传递一个参数给视图,2
, 因为第一个位置参数使用了?:
五. 指定视图参数的默认值
# URLconf
from django.urls import path
from . import views
urlpatterns = [
path('blog/', views.page),
path('blog/page<int:num>/', views.page), #int是指明num的类型,num是指明参数名
]
# View
def page(request, num=1):
......
#当匹配到第一个url, 那就会使用默认的num=1.
#当匹配到第二个url,就会使用传入的真实的num
六. extra options
urlpatterns列表里面的path()有四个参数:
- 路由
- 对应的view名字
- 可选的,定义一个字典将关键字参数传入
- name, 是一个全局的name,在templates里面用得最多
现在我们讨论的就是第三个参数(可选参数):{‘foo’: ‘bar’}
(一). passing extra options to view functions
from django.urls import path
from . import views
urlpatterns = [
path('blog/<int:year>/', views.year_archive, {'foo': 'bar'}),
]
(二). passing extra options to include()
# main.py
from django.urls import include, path
urlpatterns = [
path('blog/', include('inner'), {'blog_id': 3}),
]
# inner.py
from django.urls import path
from mysite import views
urlpatterns = [
path('archive/', views.archive),
path('about/', views.about),
]
上面{'blog_id':3}
是extra options, 通过include(‘inner’)把这个{'blog_id':3}
传递给下面的archive函数和about函数了。
七. 反向解析
反向解析的意思就是找到对应的url地址。
对于反向解析,为了满足不同的层面(layers), Django提供了三个tools.
- 在templates里面可以使用 url 这个template tag
- 在views.py里面可以使用reverse()函数
- 可以使用get_absolute_url
from django.urls import path
from . import views
urlpatterns = [
#...
path('articles/<int:year>/', views.year_archive, name='news-year-archive'),
#...
]
在上面的URLconf里面已经定义了path, 如果想要找到/articles//这个路由地址,在templates可以通过如下的{% url ‘news-year-archive’ yearvar %}找到。
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
{# Or with the year in a template context variable: #}
<ul>
{% for yearvar in year_list %}
<li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li>
{% endfor %}
</ul>
在python code里面可以通过如下 return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
找到URLconf里面定义的路由。
from django.http import HttpResponseRedirect
from django.urls import reverse
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
八. URL namespace
- application namespace
每一个应用的实例会有一个同样的命名空间。也就是多个实例共享一个命名空间。
- instance namespace
- 实例命名空间定义了一个特定的应用的实例,实例命名空间需要在你的整个项目中都是独一无二的
- 实例命名空间可以和应用命名空间一致,这被用作一个应用实例的默认实例
- namespaced URLs使用":"来进行分割,比如
admin:index
指的就是admin 应用里面的index 页面。admin是namespace, index是URLconf里面每个path里面定义的name - 命名空间也可以是嵌套的,比如
sports:polls:index
,