将 Pk 或 Slug 传递给 Django 中的通用 DetailView?
Passing Pk or Slug to Generic DetailView in Django?
我是 Django Class 基于视图的新手。我正在尝试制作一个简单的视图来获取 post 的详细信息。
我的 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 没有传递到通用详细视图。我该如何通过?我从 url 假设它可以接收,但它不是。
url 模式按照您定义的顺序进行检查
这里是:
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 的各种情况。这样更明确。
另一方面,简单地颠倒模式的顺序,将更明确的模式放在最前面也是可行的并且是正确的(这是 url 模式的 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
问题是你必须告诉 DetailView
它应该在 URL 中使用 post_id
关键字而不是默认的 pk
或 slug
为了获得将要显示的对象。
这可以通过设置 pk_url_kwarg
属性来完成:
(你的url定义也是错误的,总是以$
结束你的url定义。下面是更正后的版本)
url(r'(?P<post_id>\d+)$', GenreDetail.as_view(), name = 'post'),
url(r'(?P<post_id>\d+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
以下 url 将匹配给定上面的 url 模式:
- /2
- /2/艺伎回忆录 by-arthur-golden
from django.views.generic import DetailView
class GenreDetail(DetailView):
model = Post
template_name = "post.html"
pk_url_kwarg = "post_id"
或者,您可以在 url 中将 post_id
更改为 pk
,这样您就不必触摸视图中的任何内容:
url(r'(?P<pk>\d+)$', GenreDetail.as_view(), name = 'post'),
url(r'(?P<pk>\d+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
如果您想使用 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。
使用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")
我是 Django Class 基于视图的新手。我正在尝试制作一个简单的视图来获取 post 的详细信息。 我的 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 没有传递到通用详细视图。我该如何通过?我从 url 假设它可以接收,但它不是。
url 模式按照您定义的顺序进行检查
这里是:
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 的各种情况。这样更明确。
另一方面,简单地颠倒模式的顺序,将更明确的模式放在最前面也是可行的并且是正确的(这是 url 模式的 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
问题是你必须告诉 DetailView
它应该在 URL 中使用 post_id
关键字而不是默认的 pk
或 slug
为了获得将要显示的对象。
这可以通过设置 pk_url_kwarg
属性来完成:
(你的url定义也是错误的,总是以$
结束你的url定义。下面是更正后的版本)
url(r'(?P<post_id>\d+)$', GenreDetail.as_view(), name = 'post'),
url(r'(?P<post_id>\d+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
以下 url 将匹配给定上面的 url 模式:
- /2
- /2/艺伎回忆录 by-arthur-golden
from django.views.generic import DetailView
class GenreDetail(DetailView):
model = Post
template_name = "post.html"
pk_url_kwarg = "post_id"
或者,您可以在 url 中将 post_id
更改为 pk
,这样您就不必触摸视图中的任何内容:
url(r'(?P<pk>\d+)$', GenreDetail.as_view(), name = 'post'),
url(r'(?P<pk>\d+)/(?P<slug>[-\w]+)$', GenreDetail.as_view()),
如果您想使用 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。
使用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")