4:django url
一个干净的,优雅的URL 方案是一个高质量Web 应用程序的重要细节。
这节我们来看看django是如何做到干净优雅的url的
1:Django如何处理一个请求
- 通过ROOT_URLCONF决定根URLCONF
- 调用所有的python模块找到urlpatterns(必须是一个列表)
- 按照顺序遍历url pattern,知道找到第一个匹配的项
- 如果找到,调用相应的view函数。。。
- 如果没找到,调用合适的错误处理函数
简单的url示例
from django.conf.urls import patterns, url, include urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(\d{4})/$', 'news.views.year_archive'), (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), )
- /articles/2003/03/03/会匹配最后一个 pattern. Django 会调用函数news.views.article_detail(request, '2003', '03', '03').
- /articles/2005/3/ 一个也没有匹配上
命名组
格式为(?P<name>pattern)
示例如下
urlpatterns = patterns('', (r'^articles/2003/$', 'news.views.special_case_2003'), (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'), (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', 'news.views.article_detail'), )
这个示例和上面的示例是一样的功能,不过不同的地方是:上面的示例传的是位置参数,命名组的参数的关键字参数,这意味着你可以调整参数的位置
- /articles/2005/03/ 会调用函数news.views.month_archive(request, year='2005', month='03'), 而不是news.views.month_archive(request, '2005', '03').
事实上这不是很推荐的写法,不仅使得代码冗长,丑陋,事实上没这个必要,除非你确实想这么做
值得注意的是:
如果存在任何的命名组参数,那么非命名组参数将会被忽略;如果不存在命名组参数,所有的非命名组参数将按照顺序以位置参数的方式传进来
url(regex, view, kwargs=None, name=None, prefix='')
1:如果你有多个view函数的前缀一样,例如
urlpatterns = patterns('', (r'^articles/(\d{4})/$', 'news.views.year_archive'), (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), )
你可以这样写
urlpatterns = patterns('news.views', (r'^articles/(\d{4})/$', 'year_archive'), (r'^articles/(\d{4})/(\d{2})/$', 'month_archive'), (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'), )
2:如果你想引用其他的urlconf文件,你可以使用include这样写
urlpatterns = patterns('', # ... snip ... (r'^comments/', include('django.contrib.comments.urls')), (r'^community/', include('django_website.aggregator.urls')), (r'^contact/', include('django_website.contact.urls')), (r'^r/', include('django.conf.urls.shortcut')), # ... snip ... )
3:如果你不想引用外部的urlconf,你还可以这样写
extra_patterns = patterns('', url(r'^reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'), url(r'^charge/$', 'credit.views.charge', name='credit-charge'), ) urlpatterns = patterns('', url(r'^$', 'apps.main.views.homepage', name='site-homepage'), (r'^help/', include('apps.help.urls')), (r'^credit/', include(extra_patterns)), )
4:当你给include配置额外参数的时候,这个额外参数会被附加到被include的urlconf文件的每一条url pattern里面
#Set one: # main.py urlpatterns = patterns('', (r'^blog/', include('inner'), {'blogid': 3}), ) # inner.py urlpatterns = patterns('', (r'^archive/$', 'mysite.views.archive'), (r'^about/$', 'mysite.views.about'), ) #Set two: # main.py urlpatterns = patterns('', (r'^blog/', include('inner')), ) # inner.py urlpatterns = patterns('', (r'^archive/$', 'mysite.views.archive', {'blogid': 3}), (r'^about/$', 'mysite.views.about', {'blogid': 3}), )
这两个set是一样的意思
5:如果两个url pattern被同一个view函数处理,那么当在模板中使用url指令的时候就会发生冲突,这时候url的name参数就可以派上用场了
urlpatterns = patterns('', url(r'^archive/(\d{4})/$', archive, name="full-archive"), url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"), )
{% url arch-summary 1945 %}
{% url full-archive 2007 %}
需要注意的是,保证你使用的name参数在整个项目里面是唯一的,否则还是有可能发生冲突的
p