Передача 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()),