一个干净的,优雅的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