У цій лекції ми розглянемо динамічні URL — один із найкорисніших інструментів Django для створення гнучких маршрутів.
Динамічні URL: що це і навіщо вони потрібні?
Пам'ятаєте часи, коли сайти складалися зі сторінок типу www.mysite.com/page1.html і www.mysite.com/page2.html? Як і технології ігор, що еволюціонували від піксельних стрілялок до сучасних 3D-шутерів, веб-розробка теж не стоїть на місці - статична маршрутизація давно стала історією. Сьогодні ми маємо справу з тисячами динамічних сторінок: профілі користувачів, картки товарів, статті в блогах – список можна продовжувати безкінечно.
Уявіть ситуацію: ви робите блог зі 100 статтями. Спробуєте створити окремий маршрут для кожної статті (blog/1, blog/2 і так далі)? Спойлер: це шлях до божевілля, а ваші колеги почнуть обходити вас за кілометр. На щастя, існують динамічні URL, які рятують нас від цього головного болю.
Динамічні URL – це крута штука, яка дозволяє передавати параметри прямо в адресному рядку і використовувати їх у представленнях.
Наприклад:
- URL:
/blog/42/ - Представлення бере число
42як ID статті і показує потрібний контент.
Основи динамічних URL
У Django динамічні маршрути задаються через спеціальні шаблони у функції path() (або re_path). У цих шаблонах змінні укладаються у дужки <>. Наприклад:
from django.urls import path
from . import views
urlpatterns = [
path('blog/<int:post_id>/', views.post_detail, name='post_detail'),
]
У цьому прикладі:
blog/<int:post_id>/— це динамічний маршрут.<int:post_id>вказує, що ми очікуємо цілочисельний параметр з ім'ямpost_id.- Цей параметр буде переданий у функцію представлення
post_detail.
Приклад створення динамічного маршруту
Крок 1. Визначимо маршрут у urls.py
Створимо маршрут для відображення профілю користувача, передаючи його ID через URL.
from django.urls import path
from . import views
urlpatterns = [
path('user/<int:user_id>/', views.user_profile, name='user_profile'),
]
Крок 2. Напишемо представлення
Тепер наш маршрут має обробляти запити. Створюємо функцію представлення user_profile у файлі views.py.
from django.http import HttpResponse
# Представлення для відображення профілю користувача
def user_profile(request, user_id):
return HttpResponse(f"Ви переглядаєте профіль користувача з ID: {user_id}")
Django автоматично витягує значення <int:user_id> з URL і передає його як аргумент функції представлення.
Крок 3. Перевіримо результат
Запустіть сервер: python manage.py runserver. Потім у браузері перейдіть на адресу http://127.0.0.1:8000/user/123/. Ви побачите повідомлення:
Ви переглядаєте профіль користувача з ID: 123
Давайте поаплодуємо собі! Ви щойно створили динамічний маршрут.
Типи динамічних змінних
Ще раз нагадаємо основні типи даних для динамічних змінних в Django (навряд чи ви їх запам'ятали з першого разу):
| Тип | Приклад | Опис |
|---|---|---|
str |
<str:name> |
Будь-який рядок |
int |
<int:id> |
Ціле число |
slug |
<slug:slug> |
Склади (літери, цифри, дефіси, підкреслення) |
uuid |
<uuid:uuid> |
UUID (універсальний ідентифікатор) |
path |
<path:path> |
Рядок із символами / |
Якщо тип не вказано, Django за замовчуванням припускає str.
Приклад із різними типами маршрутів:
urlpatterns = [
path('article/<slug:slug>/', views.article_detail, name='article_detail'),
path('file/<path:file_path>/', views.file_view, name='file_view'),
path('uuid/<uuid:doc_id>/', views.document_view, name='document_view'),
]
Використання в реальному проєкті: приклад блогу
Припустимо, у нас є таблиця з постами блогу. Нам потрібно зробити так, щоб кожен пост відкривався за адресою /blog/<id>/.
Модель Post
Створимо модель поста в models.py:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=255)
content = models.TextField()
def __str__(self):
return self.title
Після цього не забудьте зробити міграції:
python manage.py makemigrations
python manage.py migrate
Представлення для поста
Тепер напишемо представлення, яке буде повертати дані поста за його ID:
from django.shortcuts import get_object_or_404
from django.http import HttpResponse
from .models import Post
def post_detail(request, post_id):
# Отримуємо об'єкт Post або повертаємо 404, якщо не знайдено
post = get_object_or_404(Post, id=post_id)
return HttpResponse(f"Title: {post.title}
Content: {post.content}")
Функція get_object_or_404 — це вбудований зручний інструмент Django, який автоматично викликає помилку 404, якщо об'єкт не знайдено. Це краще і безпечніше, ніж обробляти подібну логіку вручну.
Налаштовуємо маршрут
У urls.py додаємо маршрут для відображення постів:
from django.urls import path
from . import views
urlpatterns = [
path('blog/<int:post_id>/', views.post_detail, name='post_detail'),
]
Тепер, додавши кілька записів у базу даних, ви можете перейти на /blog/1/, /blog/2/, і побачити відповідні сторінки.
Отримання кількох параметрів з URL
Динамічні URL не обмежуються одним параметром. Ви можете передавати кілька параметрів. Наприклад:
urlpatterns = [
path('category/<str:category_name>/post/<int:post_id>/', views.category_post, name='category_post'),
]
Представлення:
def category_post(request, category_name, post_id):
return HttpResponse(f"Категорія: {category_name}, Пост ID: {post_id}")
Тепер, відкриваючи /category/python/post/42/, ви отримаєте:
Категорія: python, Пост ID: 42
Часті помилки та особливості
Якщо певний маршрут не збігається із зазначеним форматом, Django поверне помилку 404. Наприклад, при використанні
<int:id>, запит/user/abc/викличе 404. Переконайтеся, що передаєте дані правильного типу.Якщо в
urls.pyє два однакових маршрути (наприклад,path('blog/<int:id>/')іpath('blog/<str:id>/')), Django вибере перший підходящий за порядком. Будьте уважні та уникайте конфліктів.Динамічні параметри доступні тільки у представленнях, до яких прив'язаний маршрут. Неправильне використання змінних викличе
TypeError, оскільки представлення очікує певні аргументи.Якщо ви використовуєте
re_path, переконайтеся, що регулярний вираз написаний правильно. Невелика помилка може зламати весь маршрут.
Практичне завдання
- Додайте в проєкт маршрут
/profile/<slug:username>/, який повертає привітальне повідомлення для користувача за його ім'ям. - Реалізуйте маршрут
/shop/<int:category_id>/<slug:product_name>/, який відображає інформацію про товар. - Подумайте, як можна використовувати
uuidу маршрутах для більш безпечної передачі даних (наприклад, для посилань на приватні ресурси).
Для любителів складнощів: додайте контроль на рівні маршрутизації, щоб обробити випадок, якщо користувач вказує неправильні параметри.
urlpatterns = [
path('profile/<slug:username>/', views.user_greet, name='user_greet'),
path('shop/<int:category_id>/<slug:product_name>/', views.product_detail, name='product_detail'),
]
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ