Курс по Django: https://stepik.org/a/183363
Архив проекта: 09_sitewomen.zip
На этом занятии
мы с вами познакомимся со второй компонентой паттерна проектирования MTV – шаблонами (templates). Что это такое?
Вот смотрите, если мы откроем наш проект и запустим тестовый веб-сервер, то на
главной странице увидим отображение одной короткой строчки. Как вы понимаете,
полноценная HTML-страница
содержит гораздо больше информации, в том числе, заголовок и подключаемые
статические файлы. Конечно, если решать эту задачу «в лоб», то можно было бы
написать в функции представления что-то вроде:
def index(request):
return HttpResponse('''<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>''')
Но, представьте,
во что тогда превратится программа! Ее будет сложно читать, исправлять и, кроме
того, изменение HTML-страницы повлечет изменение и самого приложения.
Это полное безумие! Поэтому неудивительно, что все это выносится за пределы
приложения и организуется в виде шаблонов HTML-страниц. И
сейчас мы с вами узнаем, как в Django организованы шаблоны, где их
хранить и как подключать.
Первое, что
нужно знать, это как представляются шаблоны в Django. Работа с ними
очень похожа на работу шаблонизатора Jinja, о котором я
создавал серию занятий:
https://www.youtube.com/watch?v=cFJqMXxVNsI&list=PLA0M1Bcd0w8wfmtElObQrBbZjY6XeA06U
Далее, я буду
полагать, что вы владеете этим материалом. Если это не так, то рекомендую с ним
ознакомиться, прежде чем двигаться дальше. Также рекомендую посмотреть
документацию по шаблонам Django:
https://docs.djangoproject.com/en/4.2/topics/templates/
Итак,
предположим, что в качестве главной страницы мы бы хотели отобразить некоторый
шаблон с именем index.html. Для этого,
вначале нам нужно импортировать функции, через которые запускается встроенный в
Django шаблонизатор. В
самом простом варианте можно использовать функцию:
from django.template.loader import render_to_string
которая
загружает шаблон из файла, обрабатывает его и выдает результат в виде строки.
Например, это можно сделать так:
def index(request):
t = render_to_string('путь к шаблону index.html')
return HttpResponse(t)
И здесь мы
подошли ко второму важному вопросу: где должны располагаться шаблоны текущего
приложения Women? По умолчанию, Django ищет шаблоны в
подкаталоге templates нашего
приложения. Создадим его. По идее, мы можем располагать здесь наши файлы
шаблонов и все должно работать. Но есть один важный нюанс. В каком-либо другом
приложении также может оказаться файл с именем index.html. Тогда
фреймворк Django будет
использовать тот, что встретится первым. Чтобы этого не происходило, в templates приложения
принято создавать еще один подкаталог с именем приложения. В нашем случае – women. И уже в него
помещать файлы шаблонов. Тогда все наши файлы шаблонов будут отделяться от
других дополнительным подкаталогом и это позволит избежать коллизий имен
файлов.
Итак, создадим в
подкаталоге templates/women файл index.html с содержимым:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Главная страница</title>
</head>
<body>
<h1>Главная страница</h1>
</body>
</html>
Это будет наш первый
простейший шаблон, представляющий главную страницу сайта. И, далее, в функции render укажем путь к
этому шаблону:
def index(request):
t = render_to_string('women/index.html')
return HttpResponse(t)
Все, при
обновлении главной страницы в браузере, мы увидим этот шаблон. Как видите все
достаточно просто и удобно. Но можно сделать еще лучше и воспользоваться
функцией:
from django.shortcuts import render
которая
объединяет в себе рендер шаблона и формирование ответа сервера. В результате
функция представления index() может быть записана так:
def index(request):
return render(request, 'women/index.html')
Обратите
внимание, для корректного отображения кириллицы все шаблоны рекомендуется
сохранять в кодировке utf-8. Тем более что сам Python, начиная с
версии 3, по умолчанию использует юникод.
Давайте для
примера добавим еще одну страницу и один шаблон на наш сайт – страницу «О
сайте». Пропишем
следующие пути (в women/urls.py):
urlpatterns = [
path('', views.index, name='home'),
path('about/', views.about, name='about'),
…
]
И функцию about в файле women/views.py:
def about(request):
return render(request, 'women/about.html')
Добавим шаблон about.html:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>О сайте</title>
</head>
<body>
<h1>О сайте</h1>
</body>
</html>
И при переходе
по адресу:
http://127.0.0.1:8000/about/
этот шаблон
будет отображен.
Настройки шаблонизатора
При работе функций
render_to_string() и render() фреймворк Django использует
шаблонизатор, указанный в параметре TEMPLATES файла settings.py пакета
конфигурации. В частности мы там видим строчку:
'BACKEND': 'django.template.backends.django.DjangoTemplates',
означающую, что
используется встроенный шаблонизатор Django. Кроме того
здесь есть параметры DIRS и APP_DIRS. Параметр DIRS позволяет
прописывать нестандартные пути к файлам шаблонов, а APP_DIRS со значением True указывает
шаблонизатору Django искать шаблоны
также и внутри приложений. Причем, шаблоны сначала ищутся по коллекции DIRS, а затем уже в
приложениях. В частности, благодаря этому параметру успешно обнаруживаются наши
шаблоны index.html и about.html внутри
приложения women. Если
установить параметр APP_DIRS в значение False, то при запуске
проекта и перехода на главную страницу:
http://127.0.0.1:8000
появится ошибка:
TemplateDoesNotExist at /
говорящая, что
шаблон не был найден. Возвращая значение параметра APP_DIRS в True ошибка
пропадает.
Обратите
внимание, чтобы шаблоны нашего приложения успешно обнаруживались фреймворком Django, приложение
должно быть прописано в коллекции INSTALLED_APPS. Если мы его оттуда уберем, то
снова возникнет прежняя ошибка. Кстати, ради интереса мы можем ее исправить,
добавив абсолютный путь в коллекцию DIRS параметра TEMPLATES.
Сделать это можно следующим образом:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
BASE_DIR / 'women' / 'templates'
],
'APP_DIRS': True,
...
},
]
Мы здесь
воспользовались переменной BASE_DIR, которая хранит
абсолютный путь к нашему проекту, и добавили подкаталоги women и templates к файлам
шаблонов нашего приложения. Теперь, фреймворк Django без проблем
найдет нужные файлы и отобразит на главной странице.
Однако для
стандартных приложений так делать не стоит. Достаточно зарегистрировать
приложение в коллекции INSTALLED_APPS и создать подкаталог templates для размещения
файлов шаблонов. Это правильный стандартный подход.
Курс по Django: https://stepik.org/a/183363