我们在中级篇中学会了如何进行反向解析,但是有这样一个问题,在为 url 命名的时候,名字不能重复,否则会导致各种各样的问题。在 url 还少的时候保证不重名还是比较简单的,但是 url 多起来以后就比较难了。为了解决这样的问题,可以在 url 中加一个前缀。例如,我有一个 url 的名字叫做 'comment' ,此时,我可以为其加一个前缀,这个前缀通常是 app 名,例如:'myapp-comment'。

  这也是django所推荐的命名方式,但是这样始终是治标不治本。此时,我们就要学习 django 中 url 命名空间了。

URL 命名空间

  简介:

  URL 命名空间允许你反查到唯一的命名 URL,即使在不同的应用中使用相同的 URL 名称。(也就是可以在不同的app中使用相同的名称,为有命名困难症的程序员带来了福音)

  根据经验,第三方应用应该始终使用带命名空间的URL 。类似地,它还允许你在一个应用有多个实例部署的情况下反查URL。换句话讲,因为一个应用的多个实例共享相同的命名URL,命名空间将提供一种区分这些命名 URL 的方法。

  在一个站点上,正确使用 URL 命名空间的 Django 应用可以部署多次。例如,django.contrib.admin 具有一个 AdminSite 类,它允许你很容易地部署多个管理站点的实例。在下面的例子中,我们将讨论在两个不同的地方部署教程中的polls 应用,这样我们可以为两种不同的用户(作者和发布者)提供相同的功能。

一个URL 命名空间有两个部分,它们都是字符串

 应用命名空间
  它表示正在部署的应用的名称。一个应用的每个实例具有相同的应用命名空间。例如,可以预见Django 的管理站点的应用命名空间是'admin'。
 实例命名空间
  它表示应用的一个特定的实例。实例的命名空间在你的全部项目中应该是唯一的。但是,一个实例的命名空间可以和应用的命名空间相同。它用于表示一个应用的默认实例。例如,Django 管理站点实例具有一个默认的实例命名空间'admin'

  URL 的命名空间使用':' 操作符指定。例如,管理站点应用的主页使用'admin:index'。它表示'admin' 的一个命名空间和'index' 的一个命名URL。

  命名空间也可以嵌套。命名URL'sports:polls:index' 将在命名空间'polls'中查找'index',而poll 定义在顶层的命名空间'sports' 中。


反查带命名空间的URL

  我们在中级篇中了解到了 url 反查带来的变量,而在中级篇中,都是使用 name 进行反查,这里来看看如何对带命名空间的 url 进行反查。

例子:

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')),
]
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'),
...
]

 反查的方法和中级篇的一样,在模板中:

{% url 'polls:index' %}

 在基于类的视图的方法中:

reverse('polls:index', current_app=self.request.resolver_match.namespace)

 另外,注意,在模板中的反查需要添加 requestcurrent_app 属性,像这样:

def render_to_response(self, context, **response_kwargs):
self.request.current_app = self.request.resolver_match.namespace
return super(DetailView, self).render_to_response(context, **response_kwargs)

 这时,会有同学有疑问了, polls 这个应用命名空间设置了两行呀,那 polls 下的 index 到底指的是哪个?

 这个时候,就要看 django 的查找顺序了:

 1.如果当前有实例,也就是说我们通过 url 访问到了某个处理函数,这个函数进行反向查询的时候,例如我访问的是:author-polls/ ,这个 url 对应的处理函数要进行反向解析,此时它要解析 'polls:detail'。那么将解析到 author-polls/(?P<pk>\d+)/$ 中,也就是有实例的优先在该实例空间中查询。

 2.如果没有实例,但是有默认的实例空间,例如 app_name='polls',namespace='polls' ,和应用空间同名,这样的就叫做默认实例空间。在没有访问实例的时候,就匹配到默认实例空间中。

 3.如果没有实例,也没有默认实例空间,那么谁是最后注册的就选谁,例子中的 namespace='publisher-polls' 就是最后一个注册的(也就是下面的)。

注意:

  因为实例空间要是唯一的,所以使用 namespace:name 的模式应该也是唯一匹配的,例如这里的'author-polls:index' 将永远解析到 'author-polls' 实例的主页('publisher-polls' 类似)。


URL 命名空间和被包含的URLconf

  被包含的URLconf 的命名空间可以通过两种方式指定。

  首先,在你构造你的URL 模式时,你可以提供 应用 和 实例的命名空间给 include() 作为参数。例如

url(r'^polls/', include('polls.urls', namespace='author-polls', app_name='polls')),

  这将包含 polls.urls 中定义的URL 到应用命名空间 'polls'中,其实例命名空间为'author-polls'

  其次,你可以include 一个包含嵌套命名空间数据的对象。如果你include() 一个url() 实例的列表,那么该对象中包含的URL 将添加到全局命名空间。然而,你还可以include() 一个3个元素的元组:

(<list of url() instances>, <application namespace>, <instance namespace>)

  注意这里的应用命名空间和实例命名空间是相反的。

  实例:

from django.conf.urls import include, url

from . import views

polls_patterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
] url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))),

  这样会包含命名的URL模式进入到给定的应用和实例命名空间中。


与 url 相关的函数都在 django.conf.urls 中,下面看看里面都有哪些函数:

1. patterns(prefix, pattern_description, ...)

  这是一个废弃了的方法,在 django1.8 之前,urlpatterns 变量是该函数的实例。

例如:

from django.conf.urls import patterns, url

urlpatterns = patterns('',
url(r'^articles/([0-9]{4})/$', 'news.views.year_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', 'news.views.month_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', 'news.views.article_detail'),
)

第一个参数是一个前缀,这里的所有表示处理函数的字符串都是以 'new.views' 开头的,所有可以改写成下面这种形式:

from django.conf.urls import patterns, url

urlpatterns = patterns('news.views',
url(r'^articles/([0-9]{4})/$', 'year_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', 'month_archive'),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', 'article_detail'),
)

  因为 patterns 是python的一个方法,而 python 中,一个方法最多接受 255 个参数,也就是说最多可以在一个 patterns 中写 255-1 个 url,虽然这一般不会有什么影响,因为我们可以通过 include 方法来分离 url,而且这个方法返回的是一个列表,所以可以通过列表拼接的方式,来扩展,例如:

urlpatterns = patterns('',
...
)
urlpatterns += patterns('',
...
)

  所以也只是现在最多一次性创建多少个 url 而已。

  但是这个方法还是在 1.8 中废弃了(当然你还可强行用,到 1.9.4 为止代码并没有被移除,以后的版本另算),以后直接使用 python 列表,列表中的元素是 url() 函数的实例就行了。而 python 的列表不限制长度,只看电脑的内存有没有足够的空间,所以也算是改进了。

2. static.static(prefix, view=django.views.static.serve, **kwargs)

  如果你通过django的后台上传了一张图片,而你又想在前端显示它。一般而言 django 只提供了静态文件的支持(默认是 /static/ 开头的url请求都视为静态文件请求),而图片上传是通过 MEDIA_URL 来作为

请求的开头的,但是如果不做特殊设置,是无法显示的,此时,可以通过以下的方式:

from django.conf import settings
from django.conf.urls.static import static urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

  这是老版本的写法,新版本中直接把函数放进列表中,作为列表中的一个元素就行

  注意:这里我们并没有为 view 传参,直接用默认的就行。

  当然,这也只是在开发环境中使用,如果到了正式生产环境,这些东西还是老老实实用 web server ,例如Apache或者nginx之类的作为前方代理,django自带的 web 服务估计并发量在20左右就会挂掉,而且还不是守护进程,也就是说挂掉了不会重启,要多蛋疼有多蛋疼。

3. include(arg, namespace=None, app_name=None)

  arg:可以接受一个字符串,表示被包含的模块在哪里;也可以接受一个列表,这个列表是被包含的 url() 的实例;还可以接受一个元祖,元祖的第一个元素是一个被包含的列表,第二个元素是该列表的应用空间名,第三个元素是实例空间名。

  namespace : 实例命名空间

  app_name : 应用命名空间

4. url(regex, view, kwargs=None, name=None, prefix='')

  regex:要匹配的 url。

   view:该 url 的处理函数,可以是一个表示函数位置的字符串, 也可以是一个函数的实例。

   kwargs: 一个字典,表示传递多余的参数。

   name : 为 url 进行命名。

   prefix : if prefix: view = prefix + '.' + view  表示在 view 前加上前缀。

5.各种 handler:

  django 自带错误处理视图:

        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'

  在触发相应的错误的时候,都会转向默认的处理函数,当然我们也可以重写它们,只有在 urls.py 中导入它们,并改写成我们自己的处理函数的字符串表示就可以了。

django-url调度器-高级篇的更多相关文章

  1. Django URL调度器

    Django处理请求的流程 Django确定要使用的根URLconf模块.通常,这是ROOT_URLCONF设置的值,但如果传入 HttpRequest对象具有urlconf 属性(由中间件设置),则 ...

  2. Django 源码小剖: 更高效的 URL 调度器(URL dispatcher)

    效率问题 django 内部的 url 调度机制说白了就是给一张有关匹配信息的表, 这张表中有着 url -> action 的映射, 当请求到来的时候, 一个一个(遍历)去匹配. 中, 则调用 ...

  3. Django 源码小剖: URL 调度器(URL dispatcher)

    在刚开始接触 django 的时候, 我们尝试着从各种入门文档中创建一个自己的 django 项目, 需要在 mysite.urls.py 中配置 URL. 这是 django url 匹配处理机制的 ...

  4. URL 调度器(URL dispatcher)

    URL 调度器(URL dispatcher) 在刚开始接触 django 的时候, 我们尝试着从各种入门文档中创建一个自己的 django 项目, 需要在 mysite.urls.py 中配置 UR ...

  5. django-url调度器-中级篇

    在初级篇中,我们接触了: 1.url 的简单编写 2.两种传参的方式 3.捕获的参数总是字符串 4.为视图设置默认参数 …… 在中级篇中将更进一步. 包含其它的URLconfs 当网站非常大的时候,将 ...

  6. django url注册器组件, 响应器组件, 分页器组件

    一.url注册器的使用 1.1导入模块 from django.urls import re_path, include from .serializer import views from rest ...

  7. django-url调度器-初级篇

    Django 遵从 MVC 模型,并将其特色化为 MTV 模型.模型的核心是通过用户访问的 url 来指向处理的函数,而函数处理后返回相应的结果.所以url决定了用户访问的入口,另外表单处理的提交地址 ...

  8. Django url分发器

    视图: 视图一般都写在app的views.py中.并且视图的第一个参数永远都是request(一个HttpRequest)对象.这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息等.在视 ...

  9. django url调度

    Django的url配置相同遵循着DRY(dont repeat yourself)的规则.下面都是官方文档的样例: 首先介绍的是Django怎样处理http的请求: 1.在setting里定义ROO ...

随机推荐

  1. Xcode引入外界文件时选Create groups 或 Create folder references的区别

    一.使用Create groups 我们在项目中可以手动添加一个groups(右键点击选择New Group),但是手动添加的groups实际上并不会存在于项目的目录中,被添加进groups中的文件仍 ...

  2. NopCommerce 3.80框架研究(一) 数据访问与持久化

    NopCommerce 是一个国外的开源电商系统.3.80版本使用EF6.0 和.Net Framework 4.5.1 并引入了Autofac , Autofac是一款IOC框架,比较于其他的IOC ...

  3. 解决setInterval计时器不准的问题

    在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,因为setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在s ...

  4. python中get、post数据

    方法一:urllib2 参考:http://www.cnblogs.com/chenzehe/archive/2010/08/30/1812995.html post: #!/usr/bin/pyth ...

  5. 学习练习 java 输入输出流练习2

     编写IoDemo.java的Java应用程序,程序完成的功能是:首先读取text.txt文件内容,再通过键盘输入文件的名称为iodemo.txt,把text.txt的内容存入iodemo.txt p ...

  6. 洛谷P1268 树的重量

    P1268 树的重量 85通过 141提交 题目提供者该用户不存在 标签树形结构 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 有这种情况吗!!!! 题意似乎有问题 题目描述 树可以用来表 ...

  7. cordova 开发属于自己的插件---android

    还是需要开发出自己的插件的... 我的cordova  version is 4.0.0 1.需要新建一个文件夹为 myplugin 1.1在myplugin文件夹下 新建 plugin.xml文件 ...

  8. hql 关联查询

    HQL 带的连接语句只能是实体与 该实体的属性 进行连接 其意义就是为了优化(通过延迟加载查询关联的属性)需要进行配置 from A left join A.B where (b.flag is nu ...

  9. 织梦dedecms调用栏目的SEO标题、描述、关键字的方法

    调用SEO标题:<title>{dede:field.title/}_{dede:field.seotitle /}-{dede:global.cfg_webname/}</titl ...

  10. 【.NET】MD5的用法(对文件、字符串)

    using System;using System.IO;using System.Security.Cryptography;using System.Text;namespace ConsoleA ...