Django База [2023]: Представление на основе классов: DetailView, детальная статья #8
В данной статье мы рассмотрим ещё одно представление в Django 4.1, по которому мы будем получать одну статью по заданному полю slug
, которое мы добавили в модель Article.
Если вы хотите выразить благодарность автору сайта, статей и курса по Django, вы можете сделать это по ссылке ниже:
В прошлом уроке мы рассмотрели представление ListView для вывода статей на главной странице.
Представление на основе класса: DetailView
Это представление для получения одного объекта из набора QuerySet, получаемое по slug
или же pk
, не исключаются любые другие поля.
Давайте создадим данное представление в нашем приложении блог, в файле views.py, выложу полный файл с добавление нового кода
from django.views.generic import ListView, DetailView
from .models import Article
class ArticleListView(ListView):
model = Article
template_name = 'blog/articles_list.html'
context_object_name = 'articles'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Главная страница'
return context
class ArticleDetailView(DetailView):
model = Article
template_name = 'blog/articles_detail.html'
context_object_name = 'article'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = self.object.title
return context
Пояснения:
- model - наша модель статьи
- template_name - название нашего кастомного шаблона
- context_object_name - представленная переменная в шаблоне
- context['title] - наш заголовок передаваемый в
- self.object.title - это наш объект, т.е наша статья, у которой мы получаем заголовок.
Добавление представления в urls.py
Теперь нам необходимо добавить обработку по ссылке в urls.py нашего приложения.
from django.urls import path
from .views import ArticleListView, ArticleDetailView
urlpatterns = [
path('', ArticleListView.as_view(), name='home'),
path('articles/<str:slug>/', ArticleDetailView.as_view(), name='articles_detail'),
]
Добавление метода get_absolute_url в модель Article
Теперь нам нужно внести изменения в модель Article, добавив новую функцию:
from django.db import models
from django.core.validators import FileExtensionValidator
from django.contrib.auth import get_user_model
from django.urls import reverse
from mptt.models import MPTTModel, TreeForeignKey
class Article(models.Model):
"""
Модель постов для сайта
"""
STATUS_OPTIONS = (
('published', 'Опубликовано'),
('draft', 'Черновик')
)
title = models.CharField(verbose_name='Заголовок', max_length=255)
slug = models.CharField(verbose_name='Альт.название', max_length=255, blank=True, unique=True)
# Другие поля...
# Другие функции...
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('articles_detail', kwargs={'slug': self.slug})
Пояснения:
- Данный метод позволяет получать прямую ссылку на статью, без вызова
{% url '' %}
- Также мы импортировали
reverse
для формирования правильной ссылки.
Примечание:
- Если вы столкнулись с проблемой при сохранении поста в админ-панеле, а именно, у вас нет slug, или он одинаков, не беспокойтесь, в следующем уроке про slug мы рассмотрим решение.
Изменение шаблонов, добавление шаблона articles_detail.html
Для просмотра детальной статьи, мы из списка статей должны получать ссылку на полную новость, давайте проведем изменения в articles_list.html добавив ссылку на полную статью
{% extends 'main.html' %}
{% block content %}
{% for article in articles %}
<img src={{ article.thumbnail.url }} alt={{ article.title }} width="150"/>
<strong>{{ article.title }}</strong>
<p>{{ article.short_description }}</p>
<small>{{ article.time_create }}</small>
<hr>
<span>{{ article.category.title }}</span>
<hr>
<a href="{{ article.get_absolute_url }}">Подробнее</a>
{% endfor %}
{% endblock %}
Отлично, теперь создадим шаблон полной статьи: templates/blog/articles_detail.html
{% extends 'main.html' %}
{% block content %}
<img src={{ article.thumbnail.url }} alt={{ article.title }} width="250"/>
<strong>{{ article.title }}</strong>
<p>{{ article.full_description }}</p>
<small>{{ article.time_create }}</small>
<hr>
<span>{{ article.category.title }}</span>
{% endblock %}
Примечание: в DetailView нам не нужен цикл, поэтому напрямую обращаемся к article
, это переменная, которую мы задали в context_object_name = 'article'
.
Давайте запустим наш проект и проверим, получилось ли у нас все как надо:
Как видим, ссылка правильная. Перейдем на страницу статьи:
Отлично, у нас все получилось! Более подробно вы можете изучить DetailView в документации Django