Курс по Django: https://stepik.org/a/183363
Архив проекта: 53_sitewomen.zip
На прошлом
занятии вы должны были самостоятельно создать класс TagPostList для
отображения постов по выбранному тегу. У меня получилось следующее решение:
class TagPostList(ListView):
template_name = 'women/index.html'
context_object_name = 'posts'
allow_empty = False
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
tag = TagPost.objects.get(slug=self.kwargs['tag_slug'])
context['title'] = 'Тег: ' + tag.tag
context['menu'] = menu
context['cat_selected'] = None
return context
def get_queryset(self):
return Women.published.filter(tags__slug=self.kwargs['tag_slug']).select_related('cat')
Вы, конечно,
могли бы это сделать и по-другому. Главное, чтобы не было дублирования SQL-запросов и
страница формировалась максимально быстро.
Следующим шагом
мы с вами создадим еще один класс для отображения отдельных постов и заменим
функцию представления show_post(). Для этого хорошо подходит класс DetailView. Давайте объявим
класс ShowPost после функции show_post()
и унаследуем его то DetailView. В самом простом варианте его можно
записать следующим образом:
class ShowPost(DetailView):
model = Women
template_name = 'women/post.html'
Мы здесь сразу
указали два атрибута: model – для модели; template_name – для
используемого шаблона.
Далее пока
ничего прописывать в нем не будем, а перейдем к списку маршрутов (women/urls.py). Вместо
строки:
path('post/<slug:post_slug>/', views.show_post, name='post'),
запишем:
path('post/<slug:post_slug>/', views.ShowPost.as_view(), name='post'),
Казалось бы, мы
прописали базовый функционал. Но, при попытке просмотра какого-либо поста,
возникает исключение «AttributeError». В чем проблема? Смотрите, класс DetailView по умолчанию
пытается выбрать из указанной модели Women запись,
используя атрибут pk или slug. Но у нас формируется маршрут с
параметром post_slug из-за этого и
возникает такая ошибка.
В самом простом
случае, мы можем в шаблоне маршрута вместо post_slug записать просто
slug и тогда ошибки
уже не будет. Или же, в классе ShowPost прописать атрибут:
slug_url_kwarg = 'post_slug'
(Если
используется идентификатор, то прописывается атрибут pk_url_kwarg). Обычно, эти
атрибуты опускают и в параметрах маршрутов используют ключевые слова slug – для слага и pk – для
идентификаторов.
Итак, у нас при
попытке вывести статью отображается пустая страница. Возможно, вы уже
догадались, это из-за использования параметра post внутри шаблона post.html. По умолчанию
класс DetailView в шаблон
передает переменную с именем object и переменную с именем модели
(малыми буквами). В нашем примере – это women.
Чтобы указать другое
имя переменной для шаблона, мы в классе ShowPost должны прописать
атрибут:
context_object_name = 'post'
Тогда при
обновлении страницы, видим корректное содержимое поста. А если указать не
существующий слаг, то автоматически будет сгенерировано исключение 404 –
страница не найдена. Как видите, все делается достаточно просто.
Осталось
передать в шаблон заголовок title и пункты главного меню:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = context['post']
context['menu'] = menu
return context
Что еще нам
нужно поправить в этом классе? Да, сейчас происходит отображение статьи по
слагу вне зависимости от статуса ее публикации (она может иметь флаг is_published=False). Давайте, это
тоже исправим. Для этого в классе ShowPost нужно переопределить метод get_object(), который
отвечает за извлечение записи:
def get_object(self, queryset=None):
return get_object_or_404(Women.published, slug=self.kwargs[self.slug_url_kwarg])
Мы здесь
используем функцию get_object_or_404(), которая
возвращает одну запись из таблицы Women менеджера published, если она будет
найдена, либо сгенерирует ошибку 404 – страница не найдена.
Обратите
внимание, что в функции get_object_or_404() первым
аргументом мы передаем менеджер published. Так тоже можно делать и это
гораздо удобнее, чем прописывать отдельно дополнительное условие is_published=True. В конце концов,
мы его можем не помнить, для этого и был создан отдельный менеджер published.
Все, теперь наши
опубликованные статьи успешно отображаются в браузере.
Курс по Django: https://stepik.org/a/183363