Skip to content

Latest commit

 

History

History
273 lines (205 loc) · 10.2 KB

File metadata and controls

273 lines (205 loc) · 10.2 KB

Модуль 2. Урок 10. Теги шаблонов в Django: if и for. Тег url

Когда мы начали работать с шаблонами в Django, всё было довольно просто: мы просто подставляли данные в шаблон через двойные фигурные скобки {{ }}.

Но настоящая сила шаблонов раскрывается тогда, когда мы начинаем управлять тем, что и как отображается на странице. Для этого Django предлагает теги шаблонов — особые конструкции, которые добавляют логику прямо внутрь HTML.

Сегодня мы познакомимся с самыми базовыми, но крайне важными тегами:

  • {% for %} — для циклов (перебора элементов);
  • {% if %} — для условий;
  • {% url %} — для формирования ссылок на основе маршрутов.

1. Циклы в шаблонах: тег {% for %}

Представим, что у нас есть база фильмов (в будущем мы будем брать их из модели, но пока сделаем простую имитацию):

# views.py
from django.shortcuts import render

data_db = [
    {'id': 1, 'title': 'Inception', 'description': 'Фильм о снах и реальности.', 'is_published': True},
    {'id': 2, 'title': 'Tenet', 'description': 'Фильм, где время идёт в обратную сторону.', 'is_published': False},
    {'id': 3, 'title': 'Interstellar', 'description': 'Фильм о космосе и времени.', 'is_published': True},
]

def index(request):
    data = {
        'title': 'Главная страница',
        'menu': ['Главная', 'Фильмы', 'Контакты'],
        'films': data_db,
    }
    return render(request, 'movies/index.html', context=data)

Теперь создадим шаблон index.html:

<!DOCTYPE html>
<html lang="ru">
  <head>
    <title>{{ title }}</title>
  </head>
  <body>
    <h1>{{ title }}</h1>
    <p>{{ menu|join:" | " }}</p>

    <ul>
      {% for film in films %}
      <li>
        <h2>{{ film.title }}</h2>
        <p>{{ film.description }}</p>
        <hr />
      </li>
      {% endfor %}
    </ul>
  </body>
</html>

Теперь запусти сервер и открой страницу / в браузере. Ты должен увидеть список фильмов с их описанием.


2. Добавляем условия: тег {% if %}

На странице отображаются все фильмы, включая те, у которых is_published=False. Давайте скроем неопубликованные фильмы.

<ul>
  {% for film in films %}
    {% if film.is_published %}
      <li>
        <h2>{{ film.title }}</h2>
        <p>{{ film.description }}</p>
        {% if not forloop.last %}
        <hr />
        {% endif %}
      </li>
    {% endif %}
  {% endfor %}
</ul>

Теперь в браузере будут показаны только опубликованные фильмы (is_published=True).

Обрати внимание на переменную forloop.last. Django предоставляет набор специальных переменных внутри цикла:

Переменная Значение
forloop.counter Номер итерации, начиная с 1
forloop.counter0 Номер итерации, начиная с 0
forloop.first True, если это первая итерация
forloop.last True, если это последняя итерация

Попробуй использовать forloop.counter, чтобы пронумеровать фильмы:

<li>
  <h2>{{ forloop.counter }}. {{ film.title }}</h2>
  <p>{{ film.description }}</p>
</li>

Теперь каждый фильм будет выводиться с номером.


3. Динамические ссылки: тег {% url %}

До этого момента мы писали статические HTML-ссылки, например:

<a href="/film/1/">Подробнее</a>

Но в реальном приложении маршруты могут меняться. Чтобы не редактировать каждый шаблон вручную, Django предлагает тег {% url %}.


Пример с маршрутом фильма

Добавим маршруты в urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='home'),
    path('film/<int:film_id>/', views.show_film, name='film'),
]

Добавим представление:

from django.http import HttpResponse

def show_film(request, film_id):
    return HttpResponse(f"Отображение фильма с id = {film_id}")

Теперь в шаблоне создадим динамическую ссылку на фильм:

<p><a href="{% url 'film' film.id %}">Подробнее</a></p>

Если ты изменишь маршрут film/<int:film_id>/ в urls.py, Django сам подставит новое значение во все шаблоны, где используется тег {% url %}. Это делает проект гораздо более гибким и защищает от «битых ссылок».


4. Формируем главное меню с помощью цикла и url

Добавим меню в views.py:

# movies/views.py
menu = [
    {'title': "О сайте", 'url_name': 'about'},
    {'title': "Добавить фильм", 'url_name': 'add_film'},
    {'title': "Контакты", 'url_name': 'contact'},
    {'title': "Войти", 'url_name': 'login'}
]

Добавим маршруты и заглушки:

# movies/urls.py
urlpatterns = [
    path('', views.index, name='home'),
    path('about/', views.about, name='about'),
    path('add_film/', views.add_film, name='add_film'),
    path('contact/', views.contact, name='contact'),
    path('login/', views.login, name='login'),
    path('film/<int:film_id>/', views.show_film, name='film'),
]
# movies/views.py
def index(request):
    data = {
        'title': 'Главная страница',
        'menu': menu, # Добавили меню
        'films': data_db,
    }
    return render(request, 'movies/index.html', context=data)

...

def about(request):
    return HttpResponse("О сайте CinemaHub")

def add_film(request):
    return HttpResponse("Добавление фильма")

def contact(request):
    return HttpResponse("Контакты")

def login(request):
    return HttpResponse("Авторизация")

Теперь в шаблоне выведем меню:

<ul>
  <li><a href="{% url 'home' %}">Главная</a></li>
  {% for m in menu %}
    <li><a href="{% url m.url_name %}">{{ m.title }}</a></li>
  {% endfor %}
</ul>

Проверь страницу — теперь ссылки меню автоматически формируются по именам маршрутов. Если ты изменишь путь в urls.py, шаблон сам подстроится.


⚠️ Возможные ошибки

  1. Ошибка: "NoReverseMatch" Происходит, если имя маршрута указано неправильно или нет нужных аргументов. Проверь urls.py и убедись, что передаёшь все необходимые параметры.

  2. Ошибка внутри цикла for Django не поддерживает сложные выражения в шаблонах (например, film.id + 1). Если нужно обработать данные — делай это во views.py, а не в шаблоне.

  3. Забыл закрыть тег Все теги в Django (например, {% if %}, {% for %}) требуют закрытия: {% endif %}, {% endfor %} — без них шаблон не будет работать.


Практическое задание

  1. Добавь в список data_db свой любимый фильм с описанием.
  2. Сделай, чтобы он отображался в списке только если is_published=True.
  3. Добавь динамическую ссылку «Подробнее» для каждого фильма.
  4. В меню добавь пункт «Главная» и сделай, чтобы он вел на главную страницу.
  5. Попробуй поменять маршруты в urls.py и убедись, что шаблон продолжает работать без изменений.

Вопросы

  1. Для чего нужен тег {% for %} в шаблонах Django?
  2. Что делает тег {% if %} и как он используется?
  3. Как избежать вывода неопубликованных фильмов на страницу?
  4. Зачем нужен тег {% url %}?
  5. Что произойдёт, если ты изменишь маршрут в urls.py, но не используешь тег {% url %} в шаблоне?
  6. Что делает переменная forloop.counter?
  7. Что произойдёт, если забыть закрыть тег {% if %}?
  8. Почему использование тега {% url %} безопаснее, чем прописывать URL вручную?
  9. Как можно исключить последнюю горизонтальную линию <hr> в цикле?
  10. Что означает ошибка NoReverseMatch?

Предыдущий урок | Следующий урок