web-dev-qa-db-ja.com

PkまたはSlugをDjangoのGeneric DetailViewに渡しますか?

Djangoクラスベースのビューは初めてです。投稿の詳細を取得するために単純なビューを作成しようとしています。私の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に渡されません。それをどのように渡すのですか?私はそれがピックアップできるURLから推測しますが、そうではありません。

13
Coderaemon

uRLパターンは、定義した順序でチェックされます

だからここ:

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

...最初のパターンが一致しています($で終わっていないため、余分なセグメントは無視されます)

...そしてそのパターンは単一のキーワード引数のみを渡します

一般に、同じビューを指す複数のURLパターンを持つことはお勧めできません。可能であれば、特定のビューのURLのさまざまなケースを処理する単一の正規表現(例: optional groups を使用)を作成してみてください。その方がより明確です。

一方、パターンの順序を逆にして、より明示的なパターンを最初に置くことも機能し、正しくなります(これはDjango urlpatternsの規則です!)

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

@ozgurが言及しているように、ビューにpkではなくpost_idを使用するように指示する必要もあります pk_url_kwarg を設定します

11
Anentropic

Post_idまたはslugを使用して詳細を取得する場合、URLは次のようになります

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 をご覧ください。

8
Rajesh Kaushik

問題は、オブジェクトを取得するために、デフォルトのDetailViewまたはpkではなくpost_idキーワードをURLで使用する必要があることを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 /回顧録の芸者によるアーサーゴールデン

from Django.views.generic import DetailView 

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

または、URLでpost_idpkに変更するだけで、ビュー内の何も変更する必要がなくなります。

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

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")
0
Ivan Ogai