Коли ми працюємо з CBV, головне завдання представлень залишається те саме: взяти дані і передати їх у шаблон для відображення. CBV дозволяють це робити легко і елегантно за допомогою контексту. Контекст — це словник, що містить дані, які шаблон може використовувати для відображення інформації.
Метод get_context_data() надає спосіб змінити або доповнити контекст, який буде переданий у шаблон. Якщо ти коли-небудь працював з FBV, то аналогом є передача параметра context у функцію render().
Якщо ти використовуєш get_context_data() у класах на кшталт ListView, DetailView або TemplateView, Django автоматично додає в контекст дані, засновані на властивостях твого представлення. Наприклад, для ListView у контексті вже буде доступний ключ 'object_list' із набором даних. Однак іноді цього недостатньо, і нам потрібно додати туди щось своє. Саме в таких випадках перевизначення методу get_context_data() стає особливо корисним.
Налаштування get_context_data()
Перевизначення методу виглядає досить просто. Ми доповнюємо контекст новими даними, а потім повертаємо його. Ось базовий приклад:
from django.views.generic import TemplateView
class MyTemplateView(TemplateView):
template_name = "my_template.html"
def get_context_data(self, **kwargs):
# Отримуємо базовий контекст
context = super().get_context_data(**kwargs)
# Додаємо нові дані до контексту
context['my_key'] = 'Привіт, Django!'
context['numbers'] = [1, 2, 3, 4, 5]
# Повертаємо оновлений контекст
return context
У цьому прикладі:
- Метод
super().get_context_data(**kwargs)отримує існуючий контекст (якщо він є). - Ми додаємо ключі
'my_key'і'numbers'зі своїми значеннями. - Фінальний контекст повертається в шаблон.
Приклад: Передача даних у шаблон
Ось як зміниться наш шаблон my_template.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Приклад get_context_data()</title>
</head>
<body>
<h1>{{ my_key }}</h1>
<ul>
{% for number in numbers %}
<li>{{ number }}</li>
{% endfor %}
</ul>
</body>
</html>
Після виконання розмітка сторінки виглядатиме так:
<h1>Привіт, Django!</h1>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
Практичний приклад: новини на головній сторінці
Уявіть, що ви створюєте сайт із новинами. Головна сторінка має відображати останні новини, статистику відвідувачів і список категорій. Ми реалізуємо це за допомогою get_context_data().
Модель
Спочатку створимо модель для зберігання новин:
from django.db import models
class News(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Представлення
Тепер налаштуємо представлення:
from django.views.generic import TemplateView
from .models import News
class HomePageView(TemplateView):
template_name = "home.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Передаємо список останніх новин
context['latest_news'] = News.objects.all().order_by('-created_at')[:5]
# Імітуємо статистику відвідувачів
context['visitor_count'] = 12345
# Список категорій новин
context['categories'] = ['Політика', 'Технології', 'Спорт', 'Розваги']
return context
Шаблон
Шаблон home.html для відображення контексту:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Головна сторінка</title>
</head>
<body>
<h1>Ласкаво просимо!</h1>
<p>Статистика відвідувань: {{ visitor_count }}</p>
<h2>Останні новини</h2>
<ul>
{% for news in latest_news %}
<li>{{ news.title }} ({{ news.created_at|date:"d-m-Y" }})</li>
{% endfor %}
</ul>
<h2>Категорії</h2>
<ul>
{% for category in categories %}
<li>{{ category }}</li>
{% endfor %}
</ul>
</body>
</html>
Оптимізація та створення складного контексту
Якщо контекст вашого шаблону починає розростатися, його управління стає складним. У таких випадках можна винести частину логіки в окремі функції або методи.
Припустимо, ви хочете винести підрахунок статистики та отримання списку категорій в окремі методи:
from django.views.generic import TemplateView
from .models import News
class HomePageView(TemplateView):
template_name = "home.html"
def get_latest_news(self):
return News.objects.all().order_by('-created_at')[:5]
def get_visitor_count(self):
return 12345
def get_categories(self):
return ['Політика', 'Технології', 'Спорт', 'Розваги']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['latest_news'] = self.get_latest_news()
context['visitor_count'] = self.get_visitor_count()
context['categories'] = self.get_categories()
return context
Цей підхід значно спрощує підтримку коду, оскільки кожна частина логіки ізольована.
Візуалізація: як дані передаються в шаблон
┌─────────────┐
│ Користувач │
└─────┬───────┘
│ HTTP запит
┌─────▼──────┐
│ CBV │
└─────┬──────┘
│ get_context_data()
┌─────▼──────┐
│ Контекст │
└─────┬──────┘
│
┌─────▼──────┐
│ Шаблон │
└────────────┘
Поради щодо використання get_context_data()
- Не передавайте занадто багато даних. Ключі контексту мають бути логічно обґрунтованими, інакше шаблон стане складним.
- Використовуйте методи для складної логіки. Це покращує читабельність та тестованість вашого коду.
- Делегуйте роботу моделям. Якщо логіка отримання даних складна, подумайте про створення методів у моделях або менеджерах замість написання складних запитів у представленні.
- Уникайте дублювання ключів. Якщо ключі контексту перетинаються, це може викликати конфлікт.
- Перевіряйте продуктивність. Запити до бази даних у методі
get_context_data()можуть бути "важкими". Використовуйте інструменти оптимізації, такі якselect_related()таprefetch_related().
Часті помилки при роботі з get_context_data()
- Перевизначення без виклику
super(). Якщо ти забудеш викликатиsuper().get_context_data(**kwargs), ти втратиш стандартні дані, які додає Django. - Дублювання ключів. Якщо ти випадково додаси в контекст ключ, який уже існує, це може призвести до неочікуваної поведінки.
- Надмірні дані. Ніхто не хоче бачити контекст, який важить, як енциклопедія.
Тепер у тебе є потужний інструмент для передачі даних у шаблони за допомогою методу get_context_data(). Цей метод дозволяє писати лаконічний та підтримуваний код, що особливо важливо у складних веб-додатках. З практичними прикладами ти готовий застосовувати ці знання у своєму проєкті.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ