HTML страницы в Django. Render

Основы HTML позади, самое время вернуться в уютный мир бэкенда. Проекты «Анфиса» и Yatube уже научились реагировать на запросы и возвращать текстовую строку:

# ice_cream/views.py
from django.http import HttpResponse


# Главная страница
def index(request):    
    return HttpResponse('Главная страница') 

Если view-функция может вернуть клиенту текстовую строку, то почему бы ей не вернуть HTML, ведь это тоже текстовая строка!

# ice_cream/views.py
from django.http import HttpResponse

# Главная страница
def index(request):
    html_content = '<html><head><title>Анфиса для друзей</title></head><body>'
    html_content += '<h1>Главная страница</h1>'
    html_content += '</body></html>'    
    return HttpResponse(html_content) 

Этот подход отлично работает (с технической точки зрения), но писать код будет ужасно неудобно:

  • HTML-код может занимать сотни строк;
  • непонятно, где начинается и заканчивается тот или иной HTML-тег;
  • сложно ловить ошибки;
  • синтаксис не подсвечивается;
  • в коде перемешаны логика (Python) и отображение (HTML).

HTML — отдельно, Python — отдельно

Решение проблемы есть: HTML-код выносят в отдельные файлы (их называют HTML-шаблоны) и при необходимости подключают их через загрузчик — loader:

from django.http import HttpResponse
# Импортируем загрузчик.
from django.template import loader


def index(request):
    # Загружаем шаблон;
    # шаблоны обычно хранят в отдельной директории.
    template = loader.get_template('ice_cream/index.html')
    # Формируем шаблон
    return HttpResponse(template.render({}, request)) 

В результате в ответ на запрос будет отправлен HTML из шаблона ice_cream/index.html.Есть и более изящный синтаксис: вернуть пользователю HTML-код из шаблонов можно посредством функции render() из раздела django.shortcuts**Эта функция делает то же самое, что и код, приведённый выше, но часть операций прячет «под капот»:

from django.shortcuts import render


def index(request):
    template = 'ice_cream/index.html'
    return render(request, template) 

Подключение HTML-шаблонов

В проекте «Анфиса для друзей» есть три view-функции и три HTML-шаблона:

  • шаблон главной страницы: index.html;
  • шаблон для для списка сортов мороженого: ice_cream_list.html;
  • шаблон подробной информации про мороженое: ice_cream_detail.html.

Нехорошо, если они будут валяться в корневой директории проекта: надо их положить в специальную директорию. Но куда?Есть две традиционные схемы хранения шаблонов: на уровне приложения и на уровне проекта.

Хранение шаблонов на уровне приложения

В директориях приложений создают папки /templates/имя_приложения/: шаблоны, используемые в приложении, хранят в них. Такой способ называют «хранить шаблоны на уровне приложения». Если следовать этой схеме в проекте «Анфиса для друзей», то шаблоны приложения ice_cream должны лежать в директории /ice_cream/templates/ice_cream/:

anfisa
├── anfisa     # Главная папка проекта
├── ice_cream  # Папка приложения
│   ├── templates <-- Директория для шаблонов
│   │   └── ice_cream       <-- Директория для шаблонов приложения ice_cream
│   │       ├── ice_cream_detail.html # Шаблон для отдельного мороженого
│   │       ├── ice_cream_list.html   # Шаблон со списком мороженого
│   │       └── index.html            # Шаблон главной страницы
│   ├── __init__.py
│   ├── admin.py   
│   ├── apps.py   
│   ├── models.py   
│   ├── test.py.py   
│   ├── urls.py
│   └── views.py   
└──  manage.py 

Этот вариант хорош в тех случаях, когда приложение планируется преобразовать в пакет Python (например, для того, чтобы можно было легко встроить его в другой проект). В работе с проектом Yatube таких планов нет, так что применим другой вариант.

Хранение шаблонов на уровне проекта

В корневой директории проекта создаётся папка /templates, в ней — папки, названные по именам приложений, и в этих папках хранятся шаблоны, относящиеся к приложениям проекта. Такой порядок хранения шаблонов называют «на уровне проекта».Согласно этому подходу шаблоны приложения ice_cream в проекте «Анфиса для друзей» должны лежать в директории /templates/ice_cream/:

anfisa
├── anfisa     #  Главная папка проекта
├── ice_cream  #  Папка приложения
├── templates   <-- Директория для шаблонов
│    └── ice_cream       <-- Директория для шаблонов приложения ice_cream
│        ├── ice_cream_detail.html # Шаблон страницы для отдельного мороженого
│        ├── ice_cream_list.html   # Шаблон страницы со списком мороженого
│        └── index.html            # Шаблон главной страницы
└──  manage.py 

Именно эту схему применим в проектах «Анфиса» и Yatube.

Настройки шаблонизатора Django

За настройки шаблонов в Django отвечает переменная TEMPLATES в файле settings.py:

  • BACKEND: под этим ключом указывается, какой язык шаблонов используется в проекте.В Django существует два языка разметки шаблонов: Django Template Language (DTL) и Jinja2. Значение по умолчанию — DjangoTemplates. Оставим его.
  • DIRS: здесь указывается список директорий, где Django будет искать шаблоны. Чтобы Django искал шаблоны на уровне проекта, нужно добавить путь до папки с шаблонами.Путь к папке с шаблонами указывается от корневой директории проекта (от папки, где лежит manage.py).Адрес корневой директория хранится в константе BASE_DIR, эта константа создаётся автоматически при создании проекта.Указывать путь к директории с шаблонами лучше не напрямую, а посредством метода path.join из стандартной библиотеки osos.path.join(BASE_DIR, 'templates').При таком подходе пути будут работать нормально на любой операционной системе: в Windows пути к директориям разделяются символом \, а в macOS и Linux применяют /; если указывать пути явно, без применения os.path.join(), при переносе проекта из системы в систему могут возникнуть проблемы.
  • APP_DIRS показывает, нужно ли искать шаблоны в папках приложений (на уровне приложений). Можно поменять на False, но лучше не надо. Ведь админ-зона Django — это встроенное приложение, а в нём шаблоны хранятся на уровне приложения.

Вот как должен выглядеть список TEMPLATES в том случае, когда шаблоны хранятся на уровне проекта:

# anfisa/settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # Добавлено: Искать шаблоны на уровне проекта
        'DIRS': [os.path.join(BASE_DIR, 'templates')],

        # Оставляем True: шаблоны встроенных приложений (например, админки)
        # нужно искать в директориях приложений
        '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',
            ]
        },
    }
] 

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

# anfisa/settings.py

# Путь к директории с шаблонами вынесен в переменную:
TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        # Добавлено: Искать шаблоны на уровне проекта
        'DIRS': [TEMPLATES_DIR],        
        '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',
            ]
        },
    }
] 

Предстартовая проверка: структура папок в templates

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

anfisa
├── anfisa/     #  Главная папка проекта
├── ice_cream/  #  Папка приложения
├── templates  <-- Директория для шаблонов
│    └── ice_cream
│        ├── ice_cream_detail.html # Шаблон подробной информации о мороженом
│        ├── ice_cream_list.html   # Шаблон списка мороженого
│        └── index.html            # Шаблон главной страницы
└──  manage.py 




Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: