用于DetailView的Django url模式

时间:2015-06-07 14:47:12

标签: python django

我正在关注此tutorial

以下是模型:

class Post(models.Model):
    title = models.CharField(max_length=200)
    pub_date = models.DateTimeField()
    text = models.TextField()
    slug = models.SlugField(max_length=40, unique=True)

    def get_absolute_url(self):
        return "/{}/{}/{}/".format(self.pub_date.year, self.pub_date.month, self.slug)

    def __unicode__(self):
        return self.title

    class Meta:
        ordering = ['-pub_date']

以下是访问帖子的网址:

from django.conf.urls import patterns, url
from django.views.generic import ListView, DetailView
from blogengine.models import Post

urlpatterns = patterns('',

    url(r'^(?P<pub_date__year>\d{4})/(?P<pub_date__month>\d{1,2})/(?P<slug>[a-zA-Z0-9-]+)/?$', DetailView.as_view(
        model=Post,
    )),
)

这段代码有趣的是在url模式中使用双下划线。我在url模式上查找了django的文档:https://docs.djangoproject.com/en/1.8/topics/http/urls/但是我找不到任何关于在url模式中使用双下划线的文档。

我对这种用法的猜测是,一个名为pub_year的关键字参数将被传递给DetailView的视图函数,而pub_year参数有两个属性year和month。

我尝试使用以下网址,但仍然可以使用:

url(r'^(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<slug>[a-zA-Z0-9-]+)/?$', DetailView.as_view(
    model=Post,
)),

所以我猜没有必要使用双下划线。

我在Django的source code

中找到了这一行

看起来像detailview(继承自SingleObjectMixin)可以使用slug来匹配记录。如果是这种情况,则不需要年份和月份参数。

所以这是我的问题:

  1. 在url模式中使用双下划线是否有任何价值?
  2. 当我将url模式减少到以下时,我在请求页面时只获得404:127.0.0.1:8000/test/(test是存储在db中的现有记录的slug)

    url(r'^/(?P<slug>[a-zA-Z0-9-]+)/?$', DetailView.as_view(
    model=Post,
    )),   
    
  3. 为什么会这样?

2 个答案:

答案 0 :(得分:1)

正则表达式中的那些?P只是capturing patterns;它们是名称,可以是您想要的任何名称,但将作为关键字参数传递。他们需要一个<name>(ex (?P<name>))或者它们将作为常规参数传递,这就是为什么你的简化示例失败了。

我个人保留__s用于数据库查找,并使用类似(?<pub_year>)的内容作为更具描述性的变量名称。

基于类的视图中有默认约定,允许您使用标准名称来编写非常简洁的代码。在DetailView,&#39; slug&#39;是默认的slug_field和slug_url_kwarg;如果您通过跟踪dispatch()模式,您将看到可以调整这些默认值的位置/它们的使用方式。 BTW:CCBV非常有用,您应该使用它,并且您的教程链接显示已损坏。

答案 1 :(得分:1)

由于尚未真正回答,但是:

  
      
  1. 在url模式中使用双下划线是否有任何价值?
  2.   

DRY,或多或少:

class SomeDetailView(...):
     def get_queryset(self):
         queryset = super(SomeDetailView, self).get_queryset()
         # grab all named URL keyword arguments and 
         # transform them into field lookup patterns.
         # Leave out slug and primary key keywords, though.
         filter_args = {
              k: v for k, v in self.kwargs.iteritems()
              if k not in (self.slug_url_kwarg, self.pk_url_kwarg)
         }
         if filter_args:
             queryset = queryset.filter(**filter_args)
         return queryset

例如pub_date__year是一个有效的field lookup您 - 尽管可能存在安全问题 - 只能通过urls.py中的命名捕获模式添加查找条件。

  
      
  1. 当我将url模式减少到以下内容时,我在请求页面时只获得404:127.0.0.1:8000/test/(test是存储在db中的现有记录的slug)
  2.   
url(r'^/(?P<slug>[a-zA-Z0-9-]+)/?$', DetailView.as_view(model=Post, )),   
       ^ leading slash 

这个常见的错误使它成为documentation

  

不需要添加前导斜杠,因为每个URL都有。例如,它是^文章,而不是^ /文章。

使用r'^(?P<slug>[a-zA-Z0-9-]+)/?$'

再试一次

但是,文档在这里有点误导。 &#34; 没有必要&#34;应该被理解为&#34; 初始的前导斜杠自动匹配,不是网址模式的一部分&#34;。