将Pk或Slug传递给Django中的Generic DetailView?

时间:2015-08-11 17:01:40

标签: python django django-class-based-views

我是基于Django Class的视图的新手。我正在尝试制作一个简单的视图来获取帖子的详细信息。 我的views.py:

from django.views.generic import ListView, View, DetailView 
class GenreDetail(DetailView):
            model = Post
            template_name = "post.html"

我的urls.py:

urlpatterns = [
        url(r'(?P<post_id>[^/]+)', GenreDetail.as_view(), name = 'post'),
        url(r'(?P<post_id>[^/]+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
    ] 

我得到的错误:

AttributeError at /2/memoirs-of-a-geisha-by-arthur-golden
Generic detail view GenreDetail must be called with either an object pk or a slug.

因此pk或slug不会传递给Generic Detailview。我怎么通过?我从网址上假设它可以接收,但事实并非如此。

4 个答案:

答案 0 :(得分:9)

按照您定义的顺序检查网址格式

所以这里:

urlpatterns = [
        url(r'(?P<post_id>[^/]+)', GenreDetail.as_view(), name = 'post'),
        url(r'(?P<post_id>[^/]+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
    ] 

...第一个模式匹配(因为它不以$结束,因此只会忽略额外的片段)

...而且该模式只传递一个关键字arg

通常,将多个url模式指向同一视图是个坏主意。如果可能的话,你应该尝试制作一个正则表达式(例如使用optional groups)来处理特定视图的url的各种情况。这种方式更明确。

另一方面,简单地颠倒模式的顺序以使更明确的模式首先也可以正常工作(这是urlpatterns的Django规则!)

urlpatterns = [
        url(r'(?P<post_id>[^/]+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
        url(r'(?P<post_id>[^/]+)', GenreDetail.as_view(), name = 'post'),
    ] 

正如@ozgur所提到的,您还需要通过设置pk_url_kwarg

告诉视图使用post_id代替pk

答案 1 :(得分:6)

如果您想使用post_id或slug获取详细信息,那么您的网址应该是这样的

url(r'post/(?P<post_id>\d+)/$', GenreDetail.as_view(), name = 'post_detail'),
url(r'post/(?P<slug>[-\w]+)/$', GenreDetail.as_view(), name = 'post_detail_slug'),

你的观点应该是这样的

from django.views.generic import DetailView 

class GenreDetail(DetailView):
    model = Post
    template_name = "post.html"
    pk_url_kwarg = "post_id"
    slug_url_kwarg = 'slug'
    query_pk_and_slug = True

有关详细信息,请阅读docs

答案 2 :(得分:4)

问题是,您必须告诉DetailView它应该在网址中使用post_id关键字而不是默认关键字pkslug才能获取对象将显示。

这可以通过设置pk_url_kwarg属性:

来完成

(您的网址定义也有误,请始终使用$结束您的网址定义。以下是更正的版本)

url(r'(?P<post_id>\d+)$', GenreDetail.as_view(), name = 'post'),
url(r'(?P<post_id>\d+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),

根据上面的网址格式,以下网址将匹配:

  • / 2
  • / 2 /回忆录对的一-艺妓逐亚瑟 - 金色
from django.views.generic import DetailView 

class GenreDetail(DetailView):
    model = Post
    template_name = "post.html"
    pk_url_kwarg = "post_id"

或者,您只需在网址中将post_id更改为pk,这样您就不必触摸视图中的任何内容:

url(r'(?P<pk>\d+)$', GenreDetail.as_view(), name = 'post'),
url(r'(?P<pk>\d+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),

答案 3 :(得分:0)

使用path

from django.urls import path
from . import views

urlpatterns = [
    path('<pk>/', views.GenreDetail.as_view(), name="post")]

对于slug

path('<slug:slug>/', views.GenreDetail.as_view(), name="post")
相关问题