现在的位置: 首页 > 综合 > 正文

Django的URLConf技巧

2018年04月30日 ⁄ 综合 ⁄ 共 2798字 ⁄ 字号 评论关闭
1、伪造捕捉到的URLConf
   如果有匹配某个模式的一推试图,以及一个并不匹配这个模式的但它的试图逻辑是一样的URL。这种情况下,可以伪造URL值的捕捉,
   这主要通过使用额外URLConf参数,使得这个多出来的URL一样使用试图。
   
   例如,你有可能有一个显示某一个特定日子的某些数据的应用,URL类似这样:
   /mydata/jan/01/
   /mydata/jan/02/
   /mydata/jan/03/
   # ...
   /mydata/dec/30/
   /mydata/dec/31/
   
   太简单了,你可以再URLconf中捕捉这些值,使用组命名
   urlpatterns = patterns('',
     (r'^mydata/(?P<Month>d{2})/(?P<Day>d{2})/$',views.my_view),
   )
   然后试图看起来可能是这样
   def my_view(request,month,day):
     #...
   这种简单方法很直接,没什么特别技术,问题如果你想添加一个使用my_view试图的URL但
   它每包含一个Month和/或者Day。
   比如你可能响增加一个这样的URL /mydata/birthday/. 这个URL等价于/mydata/jan/06,
   这时候你可以使用额外参数来达到
   urlpatterns = patterns('',
     (r'^mydata/birthday/$',views.my_view,{'Month':'jan','Day':'06'}),
     (r'^mydata/(?P<Month>d{2})/(?P<Day>d{2})/$',views.my_view),
   )  
   
   在这里最帅的地方莫过于你根本不用改变你的视图函数。视图函数只会关心它 获得 了 month 和 day 参数,
   它不会去管这些参数到底是捕捉回来的还是被额外提供的。
 
2.了解捕捉值和额外参数之间的优先级
   额外参数优先级高于捕捉值参数
   例如
   from django.conf.urls.defaults import *

   urlpatterns = patterns('',
      (r'^mydata/(?P<id>/d+)/$', views.my_view, {'id': 3}),
   )
   这里无论正则表达式匹配的Id值是多少,都会当做Id=3处理。
   所以在开发过程中,一定注意避免出现上诉情况
   
3、短路逻辑
   URLConf采用自上而下的匹配方式。
   例如一个视图
   urlpatterns = patterns('',
    # ...
    ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
    # ...
    )
   它将匹配像 /myblog/entries/add/ 和 /auth/groups/add/ 这样的URL,然而,对于用户对象的添加页面( /auth/user/add/ )是个特殊情况
   我们可以在视图里判断一下而处理
   
   视图:
   def add_stage(request,app_moudle,moudle_name):
     if app_moudle=='auth' and moudle_name=='user':
       # 处理
     else:
       #处理
   这种方法固然实现了我们的目的,但是他看上去很不优雅,我们应该将判断逻辑放到URLconf中,而不是视图中。
   这里我们利用“短路逻辑”处理
   urlpatterns = patterns('',
    # ...
    ('^auth/user/add/$', 'django.contrib.admin.views.auth.user_add_stage'),
    ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
    # ...
    )

4、包含其他URLconf

如果你试图让你的代码用在多个基于Django的站点上,你应该考虑将你的URLconf以包含的方式来处理。

在任何时候,你的URLconf都可以包含其他URLconf模块。对于根目录是基于一系列URL的站点来说,这是必要的。例如下面的,URLconf包含了其他URLConf:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^weblog/', include('mysite.blog.urls')),
    (r'^photos/', include('mysite.photos.urls')),
    (r'^about/$', 'mysite.views.about'),
)

这里有个很重要的地方:例子中的指向 include() 的正则表达式并 不 包含一个 $ (字符串结尾匹配符),但是包含了一个斜杆。每当Django遇到 include() 时,它将截断匹配的URL,并把剩余的字符串发往包含的URLconf作进一步处理。

继续看这个例子,这里就是被包含的URLconf mysite.blog.urls :

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^(/d/d/d/d)/$', 'mysite.blog.views.year_detail'),
    (r'^(/d/d/d/d)/(/d/d)/$', 'mysite.blog.views.month_detail'),
)

通过这两个URLconf,下面是一些处理请求的例子:

    *

      /weblog/2007/ :在第一个URLconf中,模式 r'^weblog/' 被匹配。因为它是一个 include() ,Django将截掉所有匹配的文本,在这里是 'weblog/' 。URL剩余的部分是 2007/ , 将在 mysite.blog.urls 这个URLconf的第一行中被匹配到。

    *

      /weblog//2007/ :在第一个URLconf中,模式 r'^weblog/' 被匹配。因为它是一个 include() ,Django将截掉所有匹配的文本,在这里是 'weblog/' 。URL剩余的部分是 /2007/ (开头有一个斜杠),将不会匹配 mysite.blog.urls 中的任何URLconf。

    *

      /about/ : 这个匹配第一个URLconf中的 mysite.views.about 视图。只是为了示范你可以混合 include() patterns和 non-include() patterns在一起使用。

抱歉!评论已关闭.