博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
django url调度
阅读量:6638 次
发布时间:2019-06-25

本文共 8842 字,大约阅读时间需要 29 分钟。

Django的url配置相同遵循着DRY(dont repeat yourself)的规则。下面都是官方文档的样例:

首先介绍的是Django怎样处理http的请求:

1、在setting里定义 ,这个值就是url的根配置,但若被request processing中间件定义了HttpRequest的urlconf属性,会替换掉

2、Django 载入模块。寻找 urlpatterns。它是pattern函数的返回值。是url的list

3、寻找每一个url pattern 直到找到第一个匹配的

4、一旦找到,会调用相应的view函数。

view函数必须带有HttpRequest对象(request),若url里没有命名參数,view函数里能够带位置參数,若有命名參数,则view函数里相同有命名參数。同一时候命名參数还有可能是 django.conf.urls.url()函数里加入的额外keyword參数。

5、若给出的url没有pattern匹配,则触发异常。

如:

from django.conf.urls import patterns, urlfrom . import viewsurlpatterns = patterns('',    url(r'^articles/2003/$', views.special_case_2003),    url(r'^articles/(\d{4})/$', views.year_archive),    url(r'^articles/(\d{4})/(\d{2})/$', views.month_archive),    url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', views.article_detail),)
注意article前不用加 /
括号的作用是捕捉传入url的值给view函数。

最后一个若请求的url是 articles/2003/03/03,调用的view 函数为views.article_detail(request, '2003', '03', '03').

在正则里分组:

url(r'^articles/(?

P<year>\d{4})/(?

P<month>\d{2})/(?P<day>\d{2})/$', views.article_detail)

则相同的url请求调用的是
views.article_detail(request, year='2003', month='03', day='03') .

django 不会处理传入的域名和查询參数,比方http://www.example.com/myapp/?page=3 仅仅能匹配myapp/

捕捉到的传给view函数的值永远是string类型的。要变成数字则须要转换。

可将不同的url指向同一个view函数。如

url(r'^blog/$', views.page),    url(r'^blog/page(?P
\d+)/$', views.page),
page函数能够有个默认的參数 num=1 。

性能:每一个正则会在第一次被訪问的时候被编译。所以速度非常快。

错误处理:若不能匹配不论什么一个正则,或有异常,django会调用错误处理的view函数。

须要在ROOT_URLCONF里指定。其它位置无效。

包含

  • handler404 – See .
  • handler500 – See .
  • handler403 – See .
  • handler400 – See .
传递string取代view函数:

url(r'^archive/$', 'mysite.views.archive'),    url(r'^about/$', 'mysite.views.about'),    url(r'^contact/$', 'mysite.views.contact'),
有同样的前缀还能够把同样的前缀写到patterns的第一个參数里:

urlpatterns = patterns('news.views',    url(r'^articles/(\d{4})/$', 'year_archive'),    url(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),    url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),)
多个前缀时能够用urlpatterns+=patterns(...) ,记住url配置也是python代码。

include的使用方法,常见使用方法:

from django.conf.urls import include, patterns, url... url(r'^comments/', include('django.contrib.comments.urls')),    url(r'^community/', include('django_website.aggregator.urls')),    url(r'^contact/', include('django_website.contact.urls')),...
include的还有一种使用方法,參数是patterns函数的返回值:

extra_patterns = patterns('',    url(r'^reports/(?

P<id>\d+)/$', credit_views.report), url(r'^charge/$', credit_views.charge), ) <pre name="code" class="python">urlpatterns = patterns('', url(r'^$', main_views.homepage), url(r'^help/', include('apps.help.urls')), url(r'^credit/', include(extra_patterns)), )

 url传递的命名參数,位置參数在include里相同有效。 

给view函数传递额外參数,在url函数里能够传递一个字典。

url(r'^blog/(?P
\d{4})/$', views.year_archive, {'foo': 'bar'}),
django会调用
views.year_archive(request, year='2005', foo='bar') .

若有同名冲突,即正则分组的名和字典里key的值同样,则取后者。

url反射:

反向获取视图相应的url是个常见的需求。硬编码(把url写死)不是DRY的做法。django在MTV各层分别提供了工具来反射获取url。

模板中: url 模板标签

python代码中。用django.core.urlresolvers.reverse()函数

模型层: get_absolute_url()方法

比如有

url(r'^articles/(\d{4})/$', views.year_archive),
的相应关系。

2012 Archive{# Or with the year in a template context variable: #}
在python代码中:

year = 2006return HttpResponseRedirect(reverse('news.views.year_archive', args=(year,)))####參数是tuple
这样当url改变时仅仅改变入口就可以。

命名urlpatterns

存在多个url相应同一个view的情况。这样当反射的时候会出现歧义。解决的方法是在定义使用url函数时加上 name=參数。

url(r'^archive/(\d{4})/$', archive, name="full-archive"),    url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, name="arch-summary"),
{% url 'arch-summary' 1945 %}{% url 'full-archive' 2007 %}
就分别相应了不同的url。

url命名空间:

url命名空间同意惟一地反射已命名的url,即使不同的app有同样的url名字。

第三方app使用命名空间是非常好的习惯。类似地。若一个应用的多个实例部署时,也同意你反射url,由于一个app的多个实例共享同样的url,命名空间提供了一种方法来区分它们。

充分利用了url命名空间的django应用可被特定网站部署多次。比如admin的AdminSite类同意你部署一个admin的多个实例。

url namespace有两部分,各自是application namespace和instance namespace。用冒号分分隔。namespace能够嵌套, 'sports:polls:index'

命名空间url的反射:e.g. 'polls:index'

1、django把命名空间分开,找application namespace,本例为polls。

这会产生一个polls 的实例的列表

2、若定义了current application(的实例)。 django找到并返回这个实例的url 解析。current application被设定为模板上下文的一个属性,期望有多部署的应用应该设定current_app 属性给每一个渲染模板的Context或者RequestContext。

3、若无current application,django寻找默认的应用实例,默认的应用实例是有和application namespace同样名称的instance namespace。本例中是polls:polls

4、若没有默认实例,django会跳出最后一次部署的应用实例,无论其instance namespace是什么。

5、若提供的namespace和第一步的application namespace不匹配。django尝试直接寻找这个namespace作为instance namespace。

如:两个polls应用的实例。一个叫author-polls。还有一个叫publisher-polls。

urls.py

from django.conf.urls import include, patterns, urlurlpatterns = patterns('',    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 patterns, urlfrom . import viewsurlpatterns = patterns('',    url(r'^$', views.IndexView.as_view(), name='index'),    url(r'^(?P
\d+)/$', views.DetailView.as_view(), name='detail'), ...)
1、若一个实例是当前实例,即。若准备在实例‘ 'author-polls中渲染datail page, 'polls:index'会解析到 'author-polls实例。也即以下的样例会返回 "/author-polls/"

reverse('polls:index', current_app=self.request.resolver_match.namespace)
{% url 'polls:index' %}

要注意current_app属性要被加到context里,

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)
2、若无当前实例,即要渲染的页面在网站上的其它页面,  
'polls:index'会解析到最后一个注冊给polls的实例。

由于没有默认的(instance namespace of 'polls')。会被解析到 'publisher-polls'

3、'author-polls:index'会一直被解到实例为 'author-polls'的索引页,还有一个也一样。

若有polls的默认实例。即实例名为polls。则上面改变的地方在第2步,会被解析为默认的实例而不是最后一个注冊的。

url命名空间和 include

两种方法

1、显式指明 application 和instance 的namespace,作为include的參数

url(r'^polls/', include('polls.urls', namespace='author-polls', app_name='polls')),
定义在polls里面的url都被增加了app_name 为 polls和instance为 author-polls的命名空间

2、include能够接受一个tuple作为參数,tuple是三元的,各自是

(
,
,
)

from . import viewspolls_patterns = patterns('',    url(r'^$', views.IndexView.as_view(), name='index'),    url(r'^(?P
\d+)/$', views.DetailView.as_view(), name='detail'),)url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))),
记得一定要传tuple。若只传送的是三个元素。则会与第一种效果一样。

可是instance 和application namespace的顺序。两种签名是相反的。django不会报错

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

最后附上 include url patterns的源代码

from importlib import import_modulefrom django.core.urlresolvers import (RegexURLPattern,    RegexURLResolver, LocaleRegexURLResolver)from django.core.exceptions import ImproperlyConfiguredfrom django.utils import six__all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'patterns', 'url']handler400 = 'django.views.defaults.bad_request'handler403 = 'django.views.defaults.permission_denied'handler404 = 'django.views.defaults.page_not_found'handler500 = 'django.views.defaults.server_error'
def
include
(
arg
,
namespace
=
None
,
app_name
=
None
):
if
isinstance
(
arg
,
tuple
):
# callable returning a namespace hint
if
namespace
:
raise
ImproperlyConfigured
(
'Cannot override the namespace for a dynamic module that provides a namespace'
)
urlconf_module
,
app_name
,
namespace
=
arg
else
:
# No namespace hint - use manually provided namespace
urlconf_module
=
arg
if
isinstance
(
urlconf_module
,
six
.
string_types
):
urlconf_module
=
import_module
(
urlconf_module
)
patterns
=
getattr
(
urlconf_module
,
'urlpatterns'
,
urlconf_module
)
# Make sure we can iterate through the patterns (without this, some
# testcases will break).
if
isinstance
(
patterns
,
(
list
,
tuple
)):
for
url_pattern
in
patterns
:
# Test if the LocaleRegexURLResolver is used within the include;
# this should throw an error since this is not allowed!
if
isinstance
(
url_pattern
,
LocaleRegexURLResolver
):
raise
ImproperlyConfigured
(
'Using i18n_patterns in an included URLconf is not allowed.'
)
return
(
urlconf_module
,
app_name
,
namespace
)
def
patterns
(
prefix
,
*
args
):
pattern_list
=
[]
for
t
in
args
:
if
isinstance
(
t
,
(
list
,
tuple
)):
t
=
url
(
prefix
=
prefix
,
*
t
)
elif
isinstance
(
t
,
RegexURLPattern
):
t
.
add_prefix
(
prefix
)
pattern_list
.
append
(
t
)
return
pattern_list
def
url
(
regex
,
view
,
kwargs
=
None
,
name
=
None
,
prefix
=
''
):
if
isinstance
(
view
,
(
list
,
tuple
)):
# For include(...) processing.
urlconf_module
,
app_name
,
namespace
=
view
return
RegexURLResolver
(
regex
,
urlconf_module
,
kwargs
,
app_name
=
app_name
,
namespace
=
namespace
)
else
:
if
isinstance
(
view
,
six
.
string_types
):
if
not
view
:
raise
ImproperlyConfigured
(
'Empty URL pattern view name not permitted (for pattern
%r
)'
%
regex
)
if
prefix
:
view
=
prefix
+
'.'
+
view
return
RegexURLPattern
(
regex
,
view
,
kwargs
,
name
)

转载地址:http://nrivo.baihongyu.com/

你可能感兴趣的文章
1.4 配置备份策略(Policy)
查看>>
STL - 常用顺序容器代码
查看>>
黑马程序员—10-宏定义、枚举、typedef
查看>>
[转] 驱动模拟键盘鼠标
查看>>
Makefile 常用函数表
查看>>
狐狸和兔子
查看>>
世界卫生组织十大垃圾食物
查看>>
启示录-打造用户喜爱的产品 读书笔记
查看>>
NoSQL-redis-单机多实例,伪分布式环境搭建
查看>>
C#使用Linq对DataGridView进行模糊查找
查看>>
javascript sort order by for array or json object
查看>>
流量查看命令
查看>>
winform横线添加
查看>>
安装linux
查看>>
poj 1463 (树形dp)
查看>>
跨域问题
查看>>
关于JFace带复选框的树
查看>>
Mongodb集群【三】
查看>>
vs2010快捷键
查看>>
4768 跳石头
查看>>