参考官方文档:https://docs.djangoproject.com/en/dev/topics/http/urls/
url处理请求的过程:
1.首先会去找模块的
ROOT_URLCONF
设置,如果HttpRequest请求含有urlconf属性,它会替代前面的设置
3.接着将每一个模式走一遍,找到第一个匹配的URL
4.找到匹配项后,调用对应的view方法,或者class view进行处理,传递参数包括HttpRequest实例,对没有名字组的将对应位置的正则表达式的参数,对有名字组的重写Kwargs参数到
django.conf.urls.url()
5.如果没有找到对应的url,将会抛出异常
匹配的两种模式:
不包含名字组的,如下处理views.article_detail(request, '2003', '03', '03').
包含名字组的,如下处理views.article_detail(request, year='2003', month='03', day='03').
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
任何捕获到的参数都是string类型的,如上面的日期
可以给view指定默认url参数值
在view的方法中可以固定参数值,如:
url(r'^blog/page(?P<num>[0-9]+)/$', views.page),
如果在url中没有匹配上num,会使用默认的1
def page(request, num="1"):
注意细节,父url不能加'$',即结尾匹配,但是需要带上'/'
url是可扩展的
1.包含其他的urls.py文件
url(r'^community/', include('django_website.aggregator.urls')),2.包含其他的url pattern : url ( r'^credit/' , include ( extra_patterns )),
extra_patterns = [ url(r'^reports/(?P<id>[0-9]+)/$', credit_views.report), url(r'^charge/$', credit_views.charge),]
3.添加前缀去重复:
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中的参数是可以传递的,blog中所有的url都包含组,username参数
url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
url可以传递额外的选项,
views.year_archive(request, year='2005', foo='bar')
.,选项必须是字典类型,如果额外的选项和匹配的参数有冲突,以额外的选项为主
url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
对于父url的额外选项,所有的子url都存在这个额外的选项
url(r'^blog/', include('inner'), {'blogid': 3}),
反向解析
反向解析在不同的层的使用
url
(
r'^articles/([0-9]{4})/$'
,
views
.
year_archive
,
name
=
'news-year-archive'
),:
1.在模板中:使用url模板标签
<a
href=
"
{%
url
'news-year-archive'
2012
%}
"
>
2012 Archive
</a>
2.在python代码中,使用
django.core.urlresolvers.reverse()方法
from django.core.urlresolvers import reverse
return HttpResponseRedirect(reverse('news-year-archive', args=(year,)))
@models.permalink
def get_absolute_url(self):
return
(
'catalog_category'
, (), {
'slug'
: self.slug })
命名空间
为了防止url重名的问题,使用命名空间
1.应用程序的命名空间
2.实例的命名空间
url(r'^author-polls/', include('polls.urls', namespace='author-polls', app_name='polls')),如何反转映射命名空间:
1.首先找应用程序的的命名空间,如polls,
3.如果没有定义当前应用,会找默认的应用实例
4.如果没有默认的应用实例,会去找最后一个应用实例
5.如果没有找到应用程序的命名空间,则会去找实例的命名空间
namespace是可以嵌套的 'sports:polls:index'
例子:
urls.py
from django.conf.urls import include, url urlpatterns = [ url(r'^author-polls/', include('polls.urls', namespace='author-polls', app_name='polls')), url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls', app_name='polls')),]
polls/urls.py
from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.IndexView.as_view(), name='index'), url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'), ...]
现在要找到
'author-polls' url
在classbaseview中:
reverse('polls:index', current_app=self.request.resolver_match.namespace)
在template中:
{% url 'polls:index' %}
在模板反射中需要加上
current_app
的模板上下文
def render_to_response(self, context, **response_kwargs): response_kwargs['current_app'] = self.request.resolver_match.namespace return super(DetailView, self).render_to_response(context, **response_kwargs)
如果没有polls:index,那么它会找到
publisher-polls',因为它是最后一个
'author-polls:index' 也是可以找到'author-polls' url的
另外一种形式的命名空间,元组的方式,它是代表全局的(
global namespace)
url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))),