Модуль 19

Контекстні процесори

Ось твій урок у стилі CS50 та енергійного Девіда Малана! Вмикай уяву, ніби ти сидиш у лекційній залі Гарварду, а я бігаю сценою, пояснюючи магію веб-розробки.


🎓 Тема: Контекстні процесори (Context Processors)

Привіт, друзі! Ласкаво просимо назад.

Сьогодні ми поговоримо про річ, яка рятує розробників від нескінченного копіювання коду. Про інструмент, який робить ваше життя простішим, а код — чистішим. Ми говоримо про Контекстні процесори.


1. 🔥 Вступ: проблема та мотивація

Уявіть, що ви будуєте великий інтернет-магазин. У вас є 50 різних сторінок: головна, каталог, сторінка товару, кошик, профіль користувача, контакти...

І на кожній з цих сторінок, у "шапці" (header), ви хочете показувати: 1. Ім'я залогіненого користувача. 2. Кількість товарів у кошику. 3. Категорії меню.

Як ви це зробите?

Варіант А (Болісний): У кожній функції-контролері (view) ви пишете один і той самий код:

def home(request):
    cart_count = get_cart_count(request)
    return render(request, 'home.html', {'cart_count': cart_count})

def product_detail(request, id):
    cart_count = get_cart_count(request) # Знову?!
    return render(request, 'product.html', {'cart_count': cart_count})

# І так 50 разів...

Я бачу ваші обличчя. Ви вже відчуваєте, що це порушує головний закон програміста — DRY (Don't Repeat Yourself). А що, як завтра вам скажуть додати туди ще й курс долара? Ви будете правити 50 файлів?

Варіант Б (Розумний): Ви використовуєте Контекстний процесор.

Аналогія: Уявіть, що ви йдете в похід. Варіант А: Перед кожним виходом з намету ви перевіряєте кишені: "Ніж взяв? Сірники взяв? Ліхтарик взяв?". Варіант Б: У вас є "розгрузка" або поясна сумка, яка завжди на вас. Ви не думаєте про неї, вона просто є.

Контекстний процесор — це ваша поясна сумка з даними, яка автоматично додається до кожного шаблону.

Без цієї теми ваш код перетвориться на спагеті. Тож давайте розберемося, як це пофіксити!


2. 🧠 Теоретична база (без сухої академічності)

Давайте зазирнемо "під капот". Що таке контекстний процесор технічно?

Це просто Python-функція. Нічого страшного, правда?

Ця функція робить лише одну річ: 1. Отримує об'єкт request (запит). 2. Повертає словник (dictionary) з даними.

Коли Django (або інший фреймворк) малює сторінку, він бере дані, які ви передали конкретно для цієї сторінки (наприклад, конкретний товар), і зливає їх зі словником, який повернув контекстний процесор.

Візуально це виглядає так:

Дані з View (специфічні)   +   Дані з Context Processor (глобальні)   =   Фінальний контекст шаблону
{'product': 'iPhone 15'}   +   {'cart_count': 5, 'user': 'Alex'}      =   Повна картина для HTML

Що треба запам'ятати:

  1. Це функція, яка приймає request.
  2. Вона мусить повертати словник (dict).
  3. Вона запускається на кожному рендері шаблону (якщо налаштована).

3. 🧪 Приклади (від простого до реального)

Приклад 1: Hello World (а точніше, футер)

Уявіть, що внизу сайту (у футері) ми хочемо завжди мати актуальний рік для копірайту (© 2024 MySite).

Створимо файл context_processors.py у нашому додатку:

import datetime

def current_year(request):
    # Повертаємо словник. Ключ 'year' стане змінною {{ year }} у шаблоні.
    return {
        'year': datetime.datetime.now().year
    }

Тепер, якщо ми підключимо це в налаштуваннях (settings.py), у будь-якому HTML-файлі ми можемо написати: <footer> © {{ year }} My Company </footer>

І це працюватиме! Магія? Ні, технології.


Приклад 2: Реальна задача (Адмін чи ні?)

Давайте трохи ускладнимо. Припустимо, ми хочемо змінювати колір фону сайту на червоний, якщо користувач — адміністратор (щоб він випадково не видалив щось на проді, думаючи, що це тест).

def admin_flag(request):
    # Питання до вас: що, як користувач не залогінений?
    # Нам треба перевірити це, щоб код не впав.

    is_admin = False
    if request.user.is_authenticated and request.user.is_superuser:
        is_admin = True

    return {
        'is_dangerous_admin_mode': is_admin
    }

Тепер у base.html:

<body class="{% if is_dangerous_admin_mode %}bg-red-100{% endif %}">
...
</body>

Питання на засипку: Чому ми повертаємо саме словник, а не просто змінну True/False? (Пауза для роздумів) Відповідь: Тому що шаблонна система очікує набір змінних "ключ-значення", щоб додати їх до загального казана даних.


4. 🛠 Практична частина

Досить теорії! Відкривайте IDE, час кодити.

Завдання 1: "Мій бренд"

Створіть процесор, який додає змінну PROJECT_NAME ("SuperApp 3000") у всі шаблони. Виведіть її в тегу <title>.

Завдання 2: "Тільки для своїх"

Напишіть процесор, який перевіряє, чи передано в URL параметр ?promo=secret. * Якщо так — повертає {'show_discount': True}. * Якщо ні — False. * У шаблоні покажіть банер: "Вам знижка 50%!".

Завдання 3: "Полагодити баг" 🐛

Студент написав такий код:

def my_processor(request):
    weather = "Sunny"
    # Забув повернути словник!

Питання: Що станеться, коли Django спробує це запустити? (Спойлер: буде помилка TypeError, бо система спробує "розпакувати" None). Виправте це.

Міні-кейс: "Вибір теми"

Придумайте логіку: якщо в cookies користувача є запис theme='dark', процесор повертає змінну theme_class='dark-mode', інакше — порожній рядок.


5. 💡 Мислення як у розробника

Ви вже вмієте писати код, але я хочу, щоб ви думали як Senior Developer.

Ось де новачки "стріляють собі в ногу" з контекстними процесорами:

⛔ Помилка №1: Важкі запити до бази даних

Уявіть, що в процесорі ви робите таке: Category.objects.all().count() (рахуєте тисячі товарів).

Чому це погано? Контекстний процесор запускається НА КОЖНІЙ СТОРІНЦІ. Це означає, що кожен клік користувача викликає запит до бази. Якщо запит повільний (наприклад, 2 секунди), то весь ваш сайт гальмує на 2 секунди. * Як думає про: "Я покладу сюди тільки легкі дані. Якщо треба щось важке — я використаю кешування".

⛔ Помилка №2: Конфлікт імен

Ви повернули {'user': 'SuperAdmin'}, але Django вже має вбудовану змінну user. Результат: Ви перезаписали стандартного юзера своїм рядком. Все зламалося. * Як думає про: "Я буду називати свої змінні унікально, наприклад, custom_user_info або site_settings".

✅ Порада з практики:

Використовуйте контекстні процесори для глобальних налаштувань (контакти підтримки, API ключі для фронтенду, версія додатку), але не для складної бізнес-логіки. Логіка має жити у View або сервісах.


6. 🧩 Підсумок

Отже, що ми сьогодні вивчили?

  1. Проблема: Передавати одні й ті самі дані в 100 шаблонів вручну — це жах.
  2. Рішення: Контекстні процесори — це функції, які "підкидають" дані в кожен шаблон автоматично.
  3. Головне правило: Повертай словник, не роби важких запитів до БД.

Тепер ви можете зробити свій сайт динамічним і зручним, не дублюючи код. Ви стали на крок ближчими до "чистої архітектури".

Що далі? А що, як нам треба втрутитися не в шаблон, а в сам процес обробки запиту ще до того, як він дійде до функції? Наприклад, заблокувати хакера за IP? На наступному уроці ми розберемо Middleware (Проміжне ПЗ). Це як фейс-контроль у нічному клубі вашого веб-додатку.

А на сьогодні — це все. Дякую! (Завіса. Оплески) 👏