Что же такое представление DetailView?
Это интересное и универсальное представление для одиночного объекта qs, получаемое по slug или же pk (primary key).
Давайте попробуем создать такое представление и получить определенную статью. Не забываем импортировать DetailView!
modules/blog/views/articles.py
from django.views.generic import ListView, DetailView
class ArticleDetailView(DetailView):
model = Article
template_name = 'modules/blog/articles/article-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] - наш заголовок передаваемый в <title></title>
- self.object.title - это наш объект, т.е наша статья, у которой мы получаем заголовок.
Давайте добавим ссылку в модель, а после в сам список статей.
modules/blog/models/articles.py (не забываем импорт from django.urls import reverse)
from django.urls import reverse
class Article(models.Model):
"""
Модель статей проекта.
"""
title = models.CharField(verbose_name=_('Заголовок'), max_length=255)
#some fields
#some methods
def get_absolute_url(self):
"""
Ссылка на статью
"""
return reverse('article-detail', kwargs={'slug': self.slug})
Пояснения:
- Данный метод позволяет получать прямую ссылку на статью, без вызова {% url '' %}
Далее идем редактировать urls.py
modules/blog/urls.py (импортируем from modules.blog.views import ArticleDetailView)
from django.urls import path
from modules.blog.views import ArticleListView, ArticleDetailView
urlpatterns = [
path('', ArticleListView.as_view(), name='article-list'),
path('<str:slug>/', ArticleDetailView.as_view(), name='article-detail'),
]
Пояснения:
- Как видите, мы добавили наше созданное представление, задали ему работу от <slug>, дали ему название article-detail.
А теперь идем в шаблон списка статей, и обновляем, добавляя метод get_absolute_url:
templates/modules/blog/articles/article-list.html
{% extends 'main.html' %}
{% block content %}
{% for article in articles %}
<figure>
<img src="{{ article.get_thumbnail }}" width="200" alt="{{ article.title }}">
</figure>
<strong>{{ article.title }}</strong>
<p>{{ article.short_description }}</p>
<a href="{{ article.get_absolute_url }}">Перейти к полной статье</a>
{% endfor %}
{% endblock %}
Пояснения:
- Мы добавили наш метод, и на скриншоте ниже мы можем видеть путь к прочтению детальной статьи

Далее, давайте создадим article-detail.html в том же месте templates/modules/blog/articles/ со следующим содержимым:
templates/modules/blog/articles/article-detail.html
{% extends 'main.html' %}
{% block content %}
<div class="card border-0">
<div class="card-body">
<div class="row">
<div class="col-md-4">
<figure>
<img src="{{ article.get_thumbnail }}" width="200" alt="{{ article.title }}">
</figure>
</div>
<div class="col-md-8">
<h5 class="card-title">
{{ article.title }}
</h5>
<small class="card-subtitle">
{{ article.created_at }} / {{ article.category }}
</small>
<div class="card-text">
{{ article.full_description }}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Пояснения:
- Как видите, цикл for нам уже не нужен в шаблоне для детальной страницы. Ведь у нас один объект получаемый по slug.
- Я использовал разметку bootstrap.
- Также, в нужную разметку я добавил поля нашего объекта.
Выглядит это следующим образом:

Также в DetailView есть много других интересных методов, как пользовательский slug_field, extra_context который отвечает за дополнительные вызовы других моделей в детальную страницу. Подробнее вы можете прочесть на официальном сайте Django.
veravel
Добрый день, у меня проблема которую я не могу понять как решить, после добавления класса в modules/models/articles.py у меня выдает ошибку: NameError: name 'AbstractBaseMeta' is not defined Подскажите что я пропустил...
Razilator
veravel, здравствуйте, в одном из уроков я создавал абстрактную модель с полями для SEO. Эту модель я создал в приложении System. Урок 18!. Вместо AbstractBaseMeta наследуйтесь в Article от models.Model, а именно:
Скорее всего, я нечаянно вставил AbstractBaseMeta из своего кода, прежде чем написать урок. Поэтому это моя вина и я исправлю статью. Если Вы следуете шаг за шагом, в 18 уроке придете к этой конструкции с AbstractBaseMeta, и поймете наследование классов и моделей.
Спасибо, что сообщили о проблеме, надеюсь у Вас все получается :)