Продовжуємо нашу подорож світом Django CBV! Сьогодні у програмі — ListView і DetailView, два класи, без яких складно уявити сучасний Django-додаток. ListView допоможе красиво вивести список усіх ваших товарів/статей/котиків, а DetailView покаже подробиці про кожен із них. І хоча на перший погляд вони здаються простими, під капотом ховається море корисних фішок, які ми зараз і розкриємо.
1. Вступ до ListView і DetailView
ListView — це клас-представлення, яке використовується для відображення списків об'єктів. Наприклад, якщо ти хочеш показати список блогів або продуктів, ListView — відмінний вибір для цього. Цей CBV автоматично готує дані у вигляді списку і передає їх у шаблон.
DetailView — це клас-представлення, призначений для показу деталей одного конкретного об'єкта. Наприклад, якщо користувач клікає на пост у блозі, щоб побачити повний текст, це завдання для DetailView. Він бере об'єкт за вказаним ідентифікатором (зазвичай pk або id) і передає його у шаблон.
2. Налаштування ListView
Ну що, давайте трохи попрограмуємо! Ми будемо використовувати наш додаток "Blog", який ми почали розробляти раніше.
Крок 1. Визначаємо модель (якщо до цього ще не зробили):
Ось модель Post, вона надає наші блогові пости:
# models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200) # Заголовок поста
content = models.TextField() # Текст поста
pub_date = models.DateTimeField(auto_now_add=True) # Дата публікації
def __str__(self):
return self.title
Крок 2. Створюємо представлення:
Тепер давайте створимо ListView, який покаже список всіх постів.
# views.py
from django.views.generic import ListView
from .models import Post
class PostListView(ListView):
model = Post # Вказуємо модель
template_name = 'post_list.html' # Ваш шаблон для відображення
context_object_name = 'posts' # Ім'я змінної контексту для списку об'єктів
Ключові параметри:
model— це модель, з якою працює представлення.template_name— шлях до вашого HTML-шаблону.context_object_name— ім'я змінної, під якою ваші дані будуть передані в шаблон.
Крок 3. Налаштовуємо маршрути:
Тепер потрібно підключити наше представлення до URL.
# urls.py
from django.urls import path
from .views import PostListView
urlpatterns = [
path('', PostListView.as_view(), name='post-list'),
]
Крок 4. Створюємо шаблон:
І, нарешті, створюємо файл post_list.html.
<!-- templates/post_list.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Список постів</title>
</head>
<body>
<h1>Список постів</h1>
<ul>
{% for post in posts %}
<li>{{ post.title }} (Опубліковано: {{ post.pub_date }})</li>
{% endfor %}
</ul>
{% if is_paginated %}
<div>
Сторінки:
{% for page_num in paginator.page_range %}
{% if page_num == page_obj.number %}
<strong>{{ page_num }}</strong>
{% else %}
<a href="?page={{ page_num }}">{{ page_num }}</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
</body>
</html>
Тепер, якщо ви запустите сервер і відкриєте головну сторінку (http://127.0.0.1:8000/), то побачите список всіх опублікованих постів.
Корисні параметри ListView
paginate_by— дозволяє налаштувати пагінацію. Наприклад,paginate_by = 5покаже по 5 об'єктів на сторінці.ordering— задає порядок сортування об'єктів. Наприклад,ordering = ['-pub_date']виведе записи в зворотному порядку публікації.
3. Налаштування DetailView
Тепер займемося DetailView. Це представлення підхоплює окремий об'єкт з бази даних і передає його в шаблон.
Крок 1. Створюємо представлення:
Додамо клас PostDetailView для відображення деталей поста.
# views.py
from django.views.generic import DetailView
class PostDetailView(DetailView):
model = Post # Модель, з якою працює представлення
template_name = 'post_detail.html' # Шаблон для відображення деталей
context_object_name = 'post' # Ім'я змінної контексту
Крок 2. Налаштовуємо маршрути:
Додамо маршрут для відображення детальної інформації про пост. Зверніть увагу на <int:pk>, який буде використовуватися для передачі ID-поста у представлення.
# urls.py
from .views import PostDetailView
urlpatterns = [
path('<int:pk>/', PostDetailView.as_view(), name='post-detail'),
]
Крок 3. Створюємо шаблон:
Тепер додамо файл post_detail.html.
<!-- templates/post_detail.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ post.title }}</title>
</head>
<body>
<h1>{{ post.title }}</h1>
<p>Опубліковано: {{ post.pub_date }}</p>
<p>{{ post.content }}</p>
<a href="/">Назад до списку</a>
</body>
</html>
Тепер, коли ви відкриєте сторінку, наприклад, http://127.0.0.1:8000/1/, ви побачите деталі поста з ID 1.
4. Комбінування ListView і DetailView
Щоб користувач міг переходити від списку постів до їх деталей, змінимо шаблон post_list.html.
<!-- templates/post_list.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Список постів</title>
</head>
<body>
<h1>Список постів</h1>
<ul>
{% for post in posts %}
<li>
<a href="{{ post.id }}/">{{ post.title }}</a>
(Опубліковано: {{ post.pub_date }})
</li>
{% endfor %}
</ul>
</body>
</html>
Тепер ви можете клікнути на будь-який пост зі списку, і він відкриється на сторінці з деталями.
5. Корисні властивості та методи
ListView: get_queryset()
Метод get_queryset() дозволяє налаштувати вибірку об'єктів, які будуть відображатися у представленні.
class PostListView(ListView):
model = Post
def get_queryset(self):
return Post.objects.filter(pub_date__year=2023) # Показуємо тільки пости 2023 року
DetailView: get_context_data()
Метод get_context_data() дозволяє додати додаткові дані в контекст шаблону.
class PostDetailView(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['extra_data'] = 'Це додаткова інформація'
return context
У шаблоні можна використовувати {{ extra_data }}.
6. Можливі помилки та їх вирішення
Іноді ти можеш зіткнутися з помилкою DoesNotExist, якщо об'єкт, який відповідає вказаному ID, не знайдено в базі даних. Щоб обробити такі випадки, використовуй метод get_object(). Туди можна додати кастомну логіку.
from django.http import Http404
class PostDetailView(DetailView):
model = Post
def get_object(self, queryset=None):
obj = super().get_object(queryset)
if not obj:
raise Http404("Пост не знайдено")
return obj
Тепер твій проєкт став набагато функціональнішим! З ListView ти можеш легко відображати списки даних, а з DetailView — показувати подробиці конкретного об'єкта. Ці інструменти допоможуть тобі швидко розробляти застосунки та зосереджуватися на бізнес-логіці, а не на нескінченному написанні однотипного коду.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ