Шаблоны Django в Python: создание и использование
В этом руководстве вы узнаете, как создавать шаблоны Django, передавать данные из функций представления в шаблоны и отображать данные в шаблонах.
Это руководство начинается с того места, где закончилось создание приложения Django.
- Введение в шаблоны Django
- Переменные
- Теги
- Фильтры
- Комментарии
- Примеры шаблонов Django
- Передача переменных в шаблон
- Создание базового шаблона
- Настройка статических файлов
Введение в шаблоны Django
В предыдущем уроке вы узнали, как вернуть HttpResponse с тегом h1 из представления. Чтобы вернуть полную страницу HTML, вам нужно будет использовать шаблон. Обратите внимание, что можно вернуть полную HTML-страницу, смешав HTML с кодом Python. Однако это непрактично и плохо масштабируется.
Шаблон — это файл, содержащий статические и динамические части веб-страницы. Для генерации динамических частей веб-страницы Django использует свой особый язык шаблонов, называемый языком шаблонов Django или DTL.
Шаблонизатор Django создает шаблоны, содержащие переменные, конструкции, теги и фильтры.
Переменные
Переменная заключена в {{ и }}. Например:
Hi {{name}}, welcome back!
В этом шаблоне name является переменной. Если значение переменной имени равно John, шаблонизатор Django преобразует указанный выше шаблон в следующий текст:
Hi John, welcome back!
Если переменная является словарем, вы можете получить доступ к элементам словаря, используя точечную нотацию (dict_name.key).
Предположим, у вас есть словарь person с двумя ключами: name и email:
person = {'name': 'John', 'email': '[email protected]'}
… вы можете получить доступ к значениям ключей имени и электронной почты словаря person в шаблоне следующим образом:
{{ person.name }} {{ person.email }}
Теги
Теги отвечают за вывод содержимого, обслуживание управляющей структуры if-else, цикла for и получение данных из базы данных.
Теги окружены {% и %}. Например:
{% csrf_token %}
В этом примере тег csrf_token генерирует токен для предотвращения CSRF-атак.
Некоторые теги, такие как if-else и for-loop, требуют начальных и конечных тегов. Например:
{% if user.is_authenticated %} Hi {{user.username}} {% endif %}
Фильтры
Фильтры преобразуют содержимое переменных и аргументов тегов. Например, чтобы сделать каждое слово в строке заглавным, используйте фильтр заголовка следующим образом:
{{ name | title }}
Если значение переменной имени равно john doe, то фильтр заголовка преобразует его в следующее:
John Doe
Некоторые фильтры принимают аргумент. Например, чтобы отформатировать дату переменной join_date в формате Ymd, используйте следующий фильтр:
{{ joined_date | date: "Y-m-d" }}
Комментарии
Комментарии будут выглядеть так:
{# This is a comment in the template #}
Шаблонизатор Django не отображает текст внутри блоков комментариев.
Примеры шаблонов Django
- Сначала создайте новый каталог под названием templates внутри каталога блога:
mkdir templates
- Во-вторых, создайте каталог блога внутри каталога шаблонов:
cd templates mkdir blog
Обратите внимание, что каталог внутри каталога templates должен иметь то же имя, что и имя приложения. В этом примере каталог blog имеет то же имя, что и приложение blog проекта Django.
- В-третьих, внутри каталога templates/blog создайте два файла шаблонов home.html и about.html со следующим содержимым.
Файл home.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Home</title> </head> <body> <h1>Home</h1> </body> </html>
Файл about.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>About</title> </head> <body> <h1>About</h1> </body> </html>
Важно отметить, что вам следует добавить приложение блога в список INSTALLED_APPS в файле settings.py, чтобы шаблоны заработали. Обычно вы делаете это сразу после создания нового приложения Django.
INSTALLED_APPS = [ # ... 'blog.apps.BlogConfig', ]
- В-четвертых, откройте файл views.py и измените функции представления home() и about() на следующие:
from django.shortcuts import render def home(request): return render(request, 'blog/home.html') def about(request): return render(request, 'blog/about.html')
В этом файле views.py мы импортируем функцию render() из django.shortcuts.
Функция render() принимает объект HttpRequest и путь к шаблону. Она визуализирует шаблон и возвращает объект HttpResponse.
- В-пятых, запустите сервер разработки Django:
python manage.py runserver
Наконец, откройте URL http://127.0.0.1:8000/ и URL http://127.0.0.1:8000/about/, вы увидите полные HTML-страницы, которые взяты из шаблонов home.html и about.html.
Передача переменных в шаблон
Мы создадим фиктивные данные записи блога и передадим их в шаблон home.html. Позже вы узнаете, как получить данные записи из базы данных.
Файл views.py будет выглядеть так:
from django.shortcuts import render posts = [ { 'title': 'Beautiful is better than ugly', 'author': 'John Doe', 'content': 'Beautiful is better than ugly', 'published_at': 'October 1, 2022' }, { 'title': 'Explicit is better than implicit', 'author': 'Jane Doe', 'content': 'Explicit is better than implicit', 'published_at': 'October 1, 2022' } ] def home(request): context = { 'posts': posts } return render(request, 'blog/home.html', context) def about(request): return render(request, 'blog/about.html')
Как это работает.
- Сначала создайте новый список (posts), в котором будут храниться фиктивные данные постов.
- Во-вторых, определите новый словарь context внутри функции home() с ключевыми постами и передайте его функции render() в качестве третьего аргумента.
Внутри шаблона home.html вы можете получить доступ к данным записи через переменную posts.
Следующий шаблон home.html, отображающий сообщения:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Blog</title> </head> <body> {% for post in posts %} <h2>{{ post.title }}</h2> <small>Published on {{ post.published_at }} by {{ post.author}}</small> <p>{{ post.content }}</p> {% endfor %} </body> </html>
Как это работает.
- Сначала используйте цикл for для итерации по переменной posts. Цикл for заканчивается endfor. И for, и endfor окружены {% и %}.
- Во-вторых, поместите значение каждого элемента в словарь, используя точечную нотацию(.).
Если вы сохраните home.html и откроете URL-адрес http://127.0.0.1:8000/, вы увидите данные поста, отображаемые на странице.
Помимо цикла for, вы можете использовать другой условный оператор, например if-else. Например:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{% if title %} {{title}} {% else %} Blog {% endif %}</title> </head> <body> {% for post in posts %} <h2>{{ post.title }}</h2> <small>Published on {{ post.published_at }} by {{ post.author}}</small> <p>{{ post.content }}</p> {% endfor %} </body> </html>
В этом примере используется оператор if-else для отображения переменной title, если она доступна, или Blog в противном случае.
Чтобы передать переменную title в шаблон home.html, вы добавляете новую запись в контекстный словарь с ключом title в функции home() следующим образом:
def home(request): context = { 'posts': posts, 'title': 'Zen of Python' } return render(request, 'blog/home.html', context)
Если вы обновите домашний URL http://127.0.0.1:8000/, вы увидите новый заголовок.
Обычно веб-сайт имеет некоторые общие разделы, такие как заголовок, нижний колонтитул и боковая панель. Чтобы не повторять их в каждом шаблоне, вы можете использовать базовый шаблон.
Создание базового шаблона
Сначала создайте новый каталог шаблонов в каталоге проекта (не в приложении блога):
├── blog ├── db.sqlite3 ├── django_project ├── manage.py ├── templates └── users
Далее добавьте каталог шаблонов в параметр TEMPLATES в файле settings.py проекта:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates' ], 'APP_DIRS': True, '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', ], }, }, ]
Обратите внимание, что BASE_DIR — это объект Path, который поступает из встроенного модуля pathlib. Косая черта / — это оператор, который объединяет объект BASE_DIR со строкой ‘templates’. Эта функция в Python называется перегрузкой операторов.
Затем создайте base.html в каталоге шаблонов со следующим кодом:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{% if title %} {{title}} {% else %} Blog {% endif %}</title> </head> <body> {% block content %} {% endblock %} </body> </html>
Base.html служит базовым шаблоном для других шаблонов. Имя базового шаблона может быть любым, например main.html.
После этого измените шаблон home.html внутри каталога templates/blog следующим образом:
{% extends 'base.html' %} {% block content %} <h1>My Posts</h1> {% for post in posts%} <h2>{{ post.title }}</h2> <small>Published on {{ post.published_at }} by {{ post.author}}</small> <p>{{ post.content }}</p> {% endfor%} {% endblock %}
Шаблон home.html расширяет шаблон base.html с помощью тега extends. Шаблон home.html имеет свой раздел для блока контента.
Также измените шаблон about.html, который расширяет шаблон base.html:
{% extends 'base.html' %} {% block content %} <h1>About</h1> {% endblock content %}
Наконец, перезапустите сервер разработки Django и откройте URL http://127.0.0.1:8000/, и вы увидите изменения.
Настройка статических файлов
Статические файлы — это CSS, JavaScript и файлы изображений, которые вы используете в шаблонах. Чтобы использовать статические файлы в шаблонах, выполните следующие действия:
- Сначала создайте статический каталог внутри каталога проекта:
mkdir static
Каталог проекта будет выглядеть так:
├── blog ├── db.sqlite3 ├── manage.py ├── mysite ├── static └── templates
- Во-вторых, задайте STATICFILES_DIRS в settings.py после файла STATIC_URL, чтобы Django мог найти статические файлы в статическом каталоге:
STATIC_URL = 'static/' STATICFILES_DIRS = [BASE_DIR / 'static']
- В-третьих, создайте три каталога js, css и images внутри статического каталога:
├── static | ├── css | ├── images | └── js
- В-четвертых, создайте style.css внутри каталога CSS со следующим содержимым.
h1{ color:#0052EA } form { max-width: 400px; } label, input, textarea, select{ display:block; width:100%; } input[type="submit"]{ display:inline-block; width:auto; } .errorlist { padding:0; margin:0; } .errorlist li{ color:red; list-style:none; } .alert{ padding:0.5rem; } .alert-success{ background-color: #dfd } .alert-error{ background-color:#ba2121; color:#fff; }
Обратите внимание, что мы используем только некоторые простые правила CSS, чтобы сделать руководства более простыми для понимания. Наш основной фокус — Django, а не CSS или JavaScript.
- В-пятых, создайте app.js внутри каталога js со следующим кодом:
setTimeout(() => { alert('Welcome to my site!'); }, 3000);
Этот код показывает предупреждение после загрузки страницы в течение 3 секунд.
- В-шестых, отредактируйте шаблон base.html, чтобы загрузить файлы style.css и app.js:
{%load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="{% static 'css/style.css' %}" /> <script src="{% static 'js/app.js' %}" defer></script> <title>My Site</title> </head> <body> {%block content%} {%endblock content%} </body> </html>
- В-седьмых, перезапустите сервер разработки Django, откройте URL-адрес http://127.0.0.1:8000/, и вы увидите, что цвет заголовка меняется в соответствии с правилом CSS.
Кроме того, примерно через 3 секунды вы увидите предупреждение, поскольку в app.js выполняется код JavaScript: