Настройка URL-маршрутизации и работа с шаблонами - Python с нуля до Junior: Путь к первой работе в IT - Qpel.AI

Настройка URL-маршрутизации и работа с шаблонами

Вы уже знаете, что Django использует архитектуру MTV (Model-Template-View). Модели работают с базой данных, а представления (Views) обрабатывают запросы. Но как Django понимает, какое представление вызвать по определённому адресу? За это отвечает URL-маршрутизация. А после обработки запроса представление должно что-то показать пользователю — здесь на помощь приходят шаблоны.

URL-маршрутизация: Путь к вашим представлениям

URL-маршрутизация в Django связывает URL-адреса, которые пользователь вводит в браузере, с нужными функциями-представлениями в вашем приложении.

Представьте, что ваш сайт — это большой дом, а URL-адреса — это адреса комнат. Система маршрутизации — это привратник, который, получив адрес комнаты, указывает, куда идти.

Как это работает?

В Django маршруты определяют в файлах urls.py. Обычно есть главный urls.py в корне проекта и отдельные urls.py в каждом приложении.

  1. Главный urls.py проекта: Это точка входа. Здесь вы "подключаете" маршруты из ваших приложений.
  2. urls.py приложения: В каждом приложении вы определяете конкретные маршруты для его функционала.

Давайте посмотрим на пример.

# project_name/urls.py (главный файл проекта)
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')), # Подключаем URL-ы из приложения 'blog'
    path('', include('main_app.urls')), # Подключаем URL-ы из приложения 'main_app' для корневого адреса
]

Здесь include('blog.urls') говорит Django: "Если URL начинается с blog/, ищи дальнейшие маршруты в файле blog/urls.py".

Теперь создадим blog/urls.py:

# blog/urls.py (файл URL-ов приложения 'blog')
from django.urls import path
from . import views # Импортируем представления из текущего приложения

urlpatterns = [
    path('', views.post_list, name='post_list'), # blog/
    path('<int:post_id>/', views.post_detail, name='post_detail'), # blog/1/, blog/25/
    path('about/', views.about_page, name='about'), # blog/about/
]

Важно: Параметр name='...' очень полезен. Он позволяет ссылаться на URL по имени, а не по жёстко заданному пути. Это делает код гибким: если вы измените URL-путь, вам не придётся менять все ссылки на него в коде, достаточно будет изменить его только в urls.py.

Типы путей в path()

  • Статические пути: path('about/', views.about_page) — для фиксированных URL.
  • Динамические пути (конвертеры): path('<int:post_id>/', views.post_detail) — позволяют захватывать части URL как переменные.
    • <int:post_id>: захватывает целое число и передаёт его как аргумент post_id в функцию post_detail.
    • Другие конвертеры: str (любая строка, кроме /), slug (строка из букв, цифр, дефисов и подчёркиваний), uuid (уникальный идентификатор), path (любая строка, включая /).

Шаблоны Django: Динамическое отображение данных

После того как представление обработало запрос и подготовило данные, их нужно красиво отобразить пользователю. Для этого в Django используют шаблоны. Шаблоны — это HTML-файлы с особыми метками, которые Django заменяет реальными данными.

Основные концепции шаблонов

  1. Переменные: Позволяют выводить данные из контекста, переданного из представления.

    <h1>Привет, {{ user_name }}!</h1>
    <p>Сегодня: {{ current_date }}</p>
    

    Переменные заключаются в двойные фигурные скобки {{ }}.

  2. Теги: Выполняют логические операции, такие как циклы, условные операторы, включение других шаблонов.

    {% if user.is_authenticated %}
        <p>Вы вошли как {{ user.username }}</p>
    {% else %}
        <p><a href="/login/">Войти</a></p>
    {% endif %}
    
    {% for item in items %}
        <li>{{ item.name }}</li>
    {% endfor %}
    

    Теги заключаются в {% %}.

  3. Фильтры: Модифицируют вывод переменных.

    <p>Цена: {{ price|floatformat:2 }} руб.</p> {# Форматирует число до двух знаков после запятой #}
    <p>Дата: {{ date|date:"d.m.Y" }}</p> {# Форматирует дату #}
    

    Фильтры применяются после переменной через вертикальную черту |.

Создание и использование шаблонов

  1. Настройка директорий шаблонов: В файле settings.py вашего проекта укажите, где Django будет искать шаблоны. Обычно это папка templates внутри каждого приложения или общая папка templates в корне проекта.

    # settings.py
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [BASE_DIR / 'templates'], # Общая папка для шаблонов проекта
            'APP_DIRS': True, # Искать шаблоны в папках 'templates' внутри каждого приложения
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
  2. Создание шаблона: Внутри папки templates вашего приложения (например, blog/templates/blog/) создайте HTML-файл, например post_list.html.

    <!-- blog/templates/blog/post_list.html -->
    <!DOCTYPE html>
    <html lang="ru">
    <head>
        <meta charset="UTF-8">
        <title>Список постов</title>
    </head>
    <body>
        <h1>Все посты</h1>
        {% if posts %}
            <ul>
                {% for post in posts %}
                    <li>
                        <h2><a href="{% url 'post_detail' post.id %}">{{ post.title }}</a></h2>
                        <p>{{ post.content|truncatechars:100 }}</p>
                    </li>
                {% endfor %}
            </ul>
        {% else %}
            <p>Постов пока нет.</p>
        {% endif %}
    </body>
    </html>
    

    Обратите внимание на {% url 'post_detail' post.id %}. Это мощный тег, который генерирует URL по имени маршрута и переданным аргументам.

  3. Рендеринг шаблона в представлении: В функции представления используйте функцию render() для объединения шаблона с данными.

    # blog/views.py
    from django.shortcuts import render
    from .models import Post # Предположим, у нас есть модель Post
    
    def post_list(request):
        posts = Post.objects.all().order_by('-pub_date') # Получаем все посты
        context = {'posts': posts} # Создаем словарь с данными для шаблона
        return render(request, 'blog/post_list.html', context)
    
    def post_detail(request, post_id):
        post = Post.objects.get(id=post_id) # Получаем конкретный пост
        context = {'post': post}
        return render(request, 'blog/post_detail.html', context)
    

    Функция render() принимает объект request, путь к шаблону и словарь context, который содержит данные, доступные в шаблоне.

Наследование шаблонов: DRY в действии

Принцип DRY (Don't Repeat Yourself — не повторяйся) очень важен в разработке. В веб-приложениях часто есть общие элементы: шапка сайта, подвал, навигация. Вместо того чтобы копировать их в каждый HTML-файл, Django предлагает наследование шаблонов.

Вы создаёте базовый шаблон (base.html) с общими элементами и "блоками", которые дочерние шаблоны могут переопределять.

<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Мой сайт{% endblock %}</title>
</head>
<body>
    <header>
        <h1>Мой крутой блог на Django</h1>
        <nav>
            <ul>
                <li><a href="{% url 'post_list' %}">Посты</a></li>
                <li><a href="{% url 'about' %}">О нас</a></li>
            </ul>
        </nav>
    </header>

    <main>
        {% block content %}
            <!-- Здесь будет основной контент дочерних шаблонов -->
        {% endblock %}
    </main>

    <footer>
        <p>&copy; 2025 Мой блог. Все права защищены.</p>
    </footer>
</body>
</html>

А дочерний шаблон будет выглядеть так:

<!-- blog/templates/blog/post_list.html -->
{% extends 'base.html' %} {# Указываем, от какого шаблона наследуемся #}

{% block title %}Список постов - {{ block.super }}{% endblock %} {# Переопределяем заголовок #}

{% block content %} {# Переопределяем блок контента #}
    <h1>Все посты</h1>
    {% if posts %}
        <ul>
            {% for post in posts %}
                <li>
                    <h2><a href="{% url 'post_detail' post.id %}">{{ post.title }}</a></h2>
                    <p>{{ post.content|truncatechars:100 }}</p>
                </li>
            {% endfor %}
        </ul>
    {% else %}
        <p>Постов пока нет.</p>
    {% endif %}
{% endblock %}

{% extends 'base.html' %} указывает, что этот шаблон наследуется от base.html. {% block title %} и {% endblock %} определяют блоки, которые могут быть переопределены. {{ block.super }} внутри блока позволяет сохранить содержимое родительского блока и добавить к нему что-то новое.

Теперь вы понимаете, как запросы пользователей попадают в нужные части вашего приложения Django и как эти части формируют динамические веб-страницы. Это основа для создания интерактивных и функциональных веб-приложений.

В следующем разделе мы углубимся в работу с админ-панелью Django, которая позволит вам управлять данными вашего приложения без написания дополнительного кода, и научимся создавать и обрабатывать веб-формы для взаимодействия с пользователем.