Передача Pk или Slug в Generic DetailView в Django?

Я новичок в представлениях на основе класса 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 не передается в общий Detailview. Как мне это пройти ? Я предполагаю, что из url он может забрать, но это не так.

3 ответов


шаблоны 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, указывающих на одно и то же представление. Если возможно, вы должны попытаться сделать одно регулярное выражение (например, используя необязательный группы), который обрабатывает различные случаи url-адреса для определенного представления. Это более ясно.

С другой стороны, просто изменив порядок ваших шаблонов, чтобы сначала поставить более явный, также будет работать и быть правильным (это правило 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 упоминает, вам также нужно сказать, что вид использовать post_id вместо pk установка pk_url_kwarg


Если вы хотите получить сведения, используя 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.


проблема в том, что вы должны сказать DetailView что нужно использовать post_id ключевое слово в URL вместо стандартных 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/мемуары-это гейша-по-Артура-золотого

from django.views.generic import DetailView 

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

кроме того, вы можете просто изменить post_id до pk в вашем url-адресе, поэтому вам не нужно ничего трогать в своем представлении:

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