这篇博客的所有知识都是从Django的URLconf所得,这篇博客只是一个重点列举。
URLconf
URL配置本质是一个网站的导航流(navigate flow),将网站各页面的url和对应的控制器连接起来,从而通过控制器实现model和view的调度,将整个网站的各个模块联结起来。首先从一段代码开始:
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匹配urlpatterns中的某一个pattern时,便会call对应的控制函数,从而调用对应的视图层和模型,将整个网站各部分结合起来。
URL传参
Django的独特之处在于可以结合正则表达式让URL自身就是参数,如下代码:
urlpatterns = [
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
]
其中(?Ppattern)表示对pattern所匹配的字符串赋值给名为name的变量,这样,对于控制函数year_archive就可以使用name变量。
扩展:下面对?在正则表达式的常用用法
1. 表示非贪婪匹配:
贪婪匹配:对于字符串“abcc”,pattern“a.*c”匹配的是尽可能长的abcc
非贪婪匹配:同样对于“abcc”,pattern”a.*?c”匹配的是尽可能短的abc
2. 表示不捕获
不捕获模式的含义是:?后跟着的正则表达式只作为判断,并不存储,也不返回,例如,“Windows(?=95|98|NT|2000)”匹配并返回“Windows2000”中的“Windows”,
1.(?:pattern):匹配pattern但不获取匹配结果
2.(?=pattern):正向肯定预查
3.(?!pattern):正向否定预查
4.(?<=pattern):反向肯定预查,与正向不同的是反向在待匹配字符串的前面,正向在后面
5.(?<!pattern):反向否定预查
3. 命名匹配字符串
如上述代码的用法:?P< year>[0-9]{4}会匹配2014然后将其赋值给名为year的字符串变量
此外,还可以传递额外参数,如:
urlpatterns = [
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]
传递名为foo的额外参数
不过仅仅通过Url传递参数是远远不够的,django参数的传递还可以有如下两种方式:
1,通过session或者cookie存储参数,供多处调用
2,在view层中的待跳转url后面直接加上参数,如”url?args1=a”
URL命名空间与include包含
如下引用django文档中的例子:
# In settings/urls/main.py
from django.conf.urls import include, url
urlpatterns = [
url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog'),namespace='foo')),
]
# In foo/urls/blog.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.blog.index),
url(r'^archive/$', views.blog.archive),
]
其中,foo就是一个命名空间(方便之后的逆向解析),include不仅可以跨文件的包含urls,还可以在同一文件中:
from django.conf.urls import include, url
from credit import views as credit_views
extra_patterns = [
url(r'^reports/$', credit_views.report),
]
urlpatterns = [
url(r'^credit/', include(extra_patterns)),
]
include用法可以简化url配置,如:
from django.conf.urls import include, url
from . import views
urlpatterns = [
url(r'^(?P<page_slug>[\w-]+)-(?P<page_id>\w+)/', include([
url(r'^history/$', views.history),
url(r'^edit/$', views.edit),
url(r'^discuss/$', views.discuss),
url(r'^permissions/$', views.permissions),
])),
]
URL逆向解析
前面所描述的都是请求的url匹配了一个模式,然后再调用对应的控制函数,逆向解析是通过对应的命名空间或者命名解析出该位置的url,然后再请求执行对应的控制函数。
1,对于单个命名的urlconf
<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>
其中2012是传递给名为’news-year-archive’ 的url的参数,此种逆向解析默认调用本命名空间的url配置
此外也可以在控制函数中的重定向申请中:
def redirect_to_year(request):
# ...
year = 2006
# ...
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
2,对于包含命名空间的urlconf(绝对路径)
在视图层的模板中:
{% url 'polls:index' %}
命名空间polls下名为“index”的urlconf
在控制函数中:
reverse('polls:index', current_app=self.request.resolver_match.namespace)
能力有限,仅作参考