Как в Django передать данные из модели в шаблон в обход views?
Допустим:
Есть main.html и там есть верхняя панель навигации (которая используется со всеми наследующими шаблонами main.html) где высвечивается имя залогиненного юзера.
И есть article.html наследующий main.html.
def article рендерит и передает переменные в article.html
И чтобы в main.html появилось имя пользователя надо его каждый раз передавать через def article:
Как это упростить до того, чтобы в main.html по умолчанию передавались данные пользователя без явной передачи каждый раз во views?
Для начала: https://www.python.org/dev/peps/pep-0020/
Один из пунктов там «явное лучше неявного».
Views в django на то и придуманы чтобы передавать данные и делать это явно, но то, как это сделать всецело зависит от Вас. Вы правы, нет смысла во всех вьюхах городить огород с передачей одних и тех же данных, тем более, если они общие для большинства шаблонов, но ни custom context processor, ни тем более custom template tag Вас не выручат так, как может одна простая конструкция:
где-нибудь в utils.py
Где-нибудь в views.py:
Таким образом Вы:
1. Не захламляете общий request flow и сохраняете контроль над контекстом любой вьюхи. Context processors будут вызваны для любого рендера, тогда как такой подход позволит Вам всегда иметь минимум необходимых данных под рукой и полный контроль над всеми вьюхами.
2. Передаете в контекст шаблонизатора только, что действительно должно в него попасть. Больше того, в отдельных вьюхах Вы даже можете переопределить базовые параметры, что не так удобно делать с context processors. (но лучше см. п.3)
3. Можете расширить абстракцию как угодно, и создать хоть 2, хоть 3, хоть больше базовых контекстов под всевозожные ситуации (зависит от архитектуры).
Убедитесь что у вас реквест есть в контекст процессорах
И тогда можете прямо в шаблонах писать
<< request.user.username >>
Если другие данные нужны, то в общем случае надо написать свой context processor или template tag.
В render_to_response надо передовать RequestContext, но проще вместо render_to_response использовать функцию render, в нее нужно передавать request.
Шаблоны (templates). Начало
На этом занятии мы с вами познакомимся с третьей компонентой паттерна проектирования MTV – шаблонами (templates). Что это такое? Вот смотрите, если мы откроем наш проект и запустим тестовый веб-сервер, то на главной странице увидим отображение одной короткой строчки. Как вы понимаете, полноценная HTML-страница содержит гораздо больше информации, в том числе, заголовок и подключаемые статические файлы. Конечно, если решать эту задачу «в лоб», то можно было бы написать в функции представления что-то вроде:
Но, представьте, во что тогда превратится программа! Ее будет сложно читать, исправлять и, кроме того, изменение HTML-страницы повлечет изменение и самого приложения. Это полное безумие! Поэтому неудивительно, что все это выносится за пределы приложения и организуется в виде шаблонов HTML-страниц. И сейчас мы с вами узнаем, как в Django организованы шаблоны, где их хранить и как подключать.
Первое, что нужно знать, это как представляются шаблоны в Django. Работа с ними очень похожа на работу шаблонизатора Jinja, о котором я создавал серию занятий:
Далее, я буду полагать, что вы владеете этим материалом. Если это не так, то рекомендую с ним ознакомиться, прежде, чем двигаться дальше. Также рекомендую посмотреть русскоязычную документацию по шаблонам Django:
Итак, предположим, что в качестве главной страницы мы бы хотели отобразить некоторый шаблон с именем index.html. Для этого, вначале нам нужно импортировать встроенный в Django шаблонизатор. По умолчанию в файле women/views.py это уже сделано вот такой строчкой:
Здесь функция render как раз и отвечает за обработку шаблонов и выдачу их в формате HTTP-ответа клиенту. Пропишем эту функцию в представлении index. В самом простом варианте это будет выглядеть так:
Здесь первый параметр обязательно должен быть ссылкой request, а второй – путь к файлу шаблона. И здесь мы подошли ко второму важному вопросу: где должны располагаться шаблоны текущего приложения Women? По умолчанию, Django ищет шаблоны в подкаталоге templates нашего приложения. Создадим его. По идее, мы можем располагать здесь наши файлы шаблонов и все должно работать. Но есть один важный нюанс. При сборке всего проекта все шаблоны от всех приложений помещаются в единую папку templates проекта и если окажется в разных приложениях два одинаковых файла (с одинаковыми именами), то возникнет неопределенность (будет взят первый попавшийся файл). Чтобы этого не происходило, в templates приложения принято создавать еще один подкаталог с именем приложения. В нашем случае – women. И уже в него помещать файлы шаблонов. Тогда при сборке этот подкаталог целиком перенесется в каталог templates проекта и коллизий имен файлов не произойдет.
Итак, создадим в подкаталоге templates/women файл index.html с содержимым:
Это будет наш первый простейший шаблон, представляющий главную страницу сайта. И, далее, в функции render укажем путь к этому шаблону:
Все, при обновлении главной страницы в браузере, мы увидим этот шаблон. Как видите все достаточно просто и удобно.
Обратите внимание, для корректного отображения кириллицы все шаблоны рекомендуется сохранять в кодировке utf-8. Тем более, что сам Python, начиная с версии 3, по умолчанию использует юникод.
Давайте для примера добавим еще одну страницу и один шаблон на наш сайт – страницу «О сайте». Пропишем следующие пути (в women/urls.py):
И функцию about в файле women/views.py:
Добавим шаблон about.html:
И при переходе по адресу:
этот шаблон будет отображен.
Передача шаблонам параметров
Я много раз произносил слово «шаблон», но что оно означает? Если посмотреть на файлы index.html или about.html, то это просто текст, который загружается и отдается браузеру по соответствующему запросу. Все так, но в этих же файлах можно прописать конструкции для отображения информации, например, из БД. Давайте для начала сделаем так, чтобы на каждой странице был свой заголовок, переданный ей через параметр title. Это можно сделать так. В файлах index.html и about.html укажем переменную title:
А в функциях представлений передать параметр title соответствующему шаблону:
Все, теперь вместо title будет подставлена строка «Главная страница» или «О сайте» и отображаться на соответствующей странице. Удобно, правда? Вот в этом и есть роль шаблонов: они описывают структуру страницы, а ее наполнение происходит динамически в самой программе.
Можно выполнять передачу и более сложных данных, например, списков. Предположим, главное меню сайта определено через список:
А, затем, в функциях представления, мы можем передать его как параметр:
Для отображения этого списка в шаблонах, очевидно нужно перебрать в цикле его элементы и сформировать отдельные пункты:
Все, если теперь перейти на сайт и отобразить, например, главную страницу, то увидим этот список в виде HTML-тегов.
Создание базового шаблона (наследование шаблонов)
Наверное, многие из вас заметили, что у нас получилось два одинаковых шаблона и для них нарушается принцип программирования:
DRY – don’t repeat yourself (не повторяйся).
Чтобы устранить этот недостаток, обычно, создается базовый шаблон представления страниц на сайте, а уже потом он расширяется шаблонами отдельных страниц. Давайте сформируем шаблон базовой страницы в виде файла base.html со следующим содержимым:
А в дочерних расширим этот базовый шаблон:
Все, теперь никакого дублирования в наших шаблонах нет и мы можем достаточно просто описывать отдельные страницы сайта, просто меняя базовый шаблон base.html.
Отображение списка статей
Теперь, когда мы в целом разобрались, что из себя представляют шаблоны, давайте выполним чтение данных из таблицы women и отобразим список статей на главной странице сайта. Для этого в модуле women/views.py выполним импорт моделей:
А, затем, в функции представления index прочитаем записи из таблицы Women и передадим коллекцию шаблону:
Видите, как просто это делается! Нам даже не нужно беспокоиться о подключении к БД. Фреймворк Django все эти операции берет на себя. Все что нам нужно – это выбрать нужные записи из таблицы и передать их в шаблон. В самом шаблоне index.html переберем эти записи и отобразим в виде списка на странице:
Все, возвращаясь на главную страницу нашего сайта, увидим список записей из БД. На мой взгляд, проще не придумаешь. Django этим и хорош. У него богатый функционал, но достаточно простой в использовании. Поэтому, даже начинающий веб-программист сможет с его помощью создавать грамотные сайты. На этом мы завершим первое знакомство с шаблонами. На последующих занятиях углубимся в эту тему и затронем фильтры и подключение статических файлов.
Видео по теме
#2. Модель MTV. Маршрутизация. Функции представления
#3. Маршрутизация, обработка исключений запросов, перенаправления
#4. Определение моделей. Миграции: создание и выполнение
#6. Шаблоны (templates). Начало
#7. Подключение статических файлов. Фильтры шаблонов
#8. Формирование URL-адресов в шаблонах
#9. Создание связей между моделями через класс ForeignKey
#10. Начинаем работу с админ-панелью
#11. Пользовательские теги шаблонов
#12. Добавляем слаги (slug) к URL-адресам
#13. Использование форм, не связанных с моделями
#14. Формы, связанные с моделями. Пользовательские валидаторы
#15. Классы представлений: ListView, DetailView, CreateView
#16. Основы ORM Django за час
#18. Постраничная навигация (пагинация)
#19. Регистрация пользователей на сайте
#20. Делаем авторизацию пользователей на сайте
#21. Оптимизация сайта с Django Debug Toolbar
#22. Включаем кэширование данных
#23. Использование капчи captcha
#24. Тонкая настройка админ панели
#25. Начинаем развертывание Django-сайта на хостинге
#26. Завершаем развертывание Django-сайта на хостинге
© 2021 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
Язык шаблонов Django ¶
Система шаблонов Django предоставляет теги, функции которых аналогичны некоторым программным структурам (тег if для логических тестов, тег for для циклов и т. Д.), Но они выполняются не только как код Python. корреспондент; Система шаблонов Django не выполняет просто какие-либо выражения Python. По умолчанию поддерживаются только теги, фильтры и синтаксис, показанные ниже (хотя при необходимости вы можете добавить свои собственные расширения к языку шаблона).
Шаблоны ¶
Вот минимальный шаблон, иллюстрирующий некоторые основные принципы. Далее в этом документе будет объяснено каждый элемент.
Зачем использовать шаблон на основе текста вместо шаблона на основе XML (например, TAL от Zope)? Мы хотели, чтобы язык шаблонов Django можно было использовать не только для шаблонов XML / HTML. Вы можете использовать язык шаблона для любого текстового формата, такого как электронная почта, JavaScript и CSV.
Переменные ¶
Технически, когда система шаблонов обнаруживает точку, она пробует следующие методы доступа в следующем порядке:
Если полученное значение является исполняемым, оно вызывается без параметров. Результат вызова становится значением шаблона.
Такой порядок поиска может привести к неожиданному поведению объектов, которые перегружают поиск по словарю. Например, рассмотрим следующий фрагмент кода, который пытается выполнить цикл по объекту collections.defaultdict :
Обратите внимание, что «bar» в выражении шаблона интерпретируется как буквальная строка, и даже если в контексте шаблона существует переменная «bar», она не будет вызываться. << foo.bar >>
Доступ к переменным атрибутам, начинающимся с подчеркивания, недоступен, поскольку они обычно считаются частными.
Фильтры ¶
Если переменная содержит значение false или пусто, этот фильтр использует указанное значение по умолчанию. В противном случае он использует значение переменной. Например :
Если value не указан или пуст, в приведенном выше коде отображается » nothing «.
Возвращает длину значения. Это работает как для текста, так и для списков. Например :
Просмотрите каждый элемент в списке. Например, чтобы отобразить список спортсменов, содержащийся в athlete_list :
Вы также можете использовать в теге фильтры и разные операторы if :
Несмотря на то, что приведенный выше пример работает, имейте в виду, что большинство шаблонных фильтров возвращают текст, поэтому математические сравнения с использованием фильтров редко работают должным образом. length это исключение.
block и extends Определяет наследование шаблонов (см. Ниже), мощный способ устранения избыточного содержимого на уровне шаблона.
Комментарии ¶
Например, этот шаблон создает контент ‘hello’ :
Комментарий может содержать любой код шаблона, действительный или нет. Например :
Наследование шаблонов ¶
Давайте рассмотрим наследование шаблонов на примере:
В этом примере тег block определяет три блока, которые могут заполняться дочерними шаблонами. Тег block только сигнализирует механизму шаблонов, что дочерний шаблон может переопределить эти части шаблона.
Дочерний шаблон может выглядеть так:
Тег extends является здесь ключевым. Он сообщает механизму шаблонов, что этот шаблон «расширяет» другой шаблон. Когда механизм шаблонов оценивает его, он сначала получает родительский объект, в данном случае «base.html».
На данный момент, шаблон двигатель замечает три метки block из base.html и заменяет эти блоки с содержимым шаблона ребенка. В зависимости от значения blog_entries результат может выглядеть так:
Вы можете использовать столько уровней наследования, сколько вам нужно. Распространенным способом использования наследования является следующий трехуровневый подход:
Такой подход максимизирует повторное использование кода и упрощает добавление элементов в области общего содержимого, например навигацию по отдельным разделам.
Вот несколько советов по наследованию:
Если вы используете в шаблоне, это должен быть первый тег в этом шаблоне. В противном случае наследование шаблона работать не будет.
Если вы обнаружите, что дублируете контент более чем в одном шаблоне, это, вероятно, означает, что вам следует поместить это содержимое в один из родительских шаблонов.
Переменные, созданные вне блока с использованием синтаксиса тега шаблона, не могут использоваться внутри блока. Например, этот шаблон вообще ничего не выдаст: as
В больших шаблонах этот метод позволяет лучше увидеть, какой тег закрывает этот тег.
Автоматический переход в HTML ¶
При создании HTML с помощью шаблонов всегда существует риск того, что переменная будет включать символы, которые изменяют созданный HTML. Например, рассмотрим этот фрагмент шаблона:
На первый взгляд это кажется безобидным способом отображения имени пользователя, но представьте, что произойдет, если пользователь введет свое имя следующим образом:
При таком значении имени шаблон будет создан следующим образом:
… Это означает, что браузер будет отображать окно предупреждения JavaScript!
Это приводит к отображению такого результата шаблона:
… Что сделало бы остальную часть веб-страницы жирной!
Ясно, что не следует слепо доверять данным, отправляемым пользователями, вставляя их непосредственно на свои веб-страницы, поскольку злоумышленник может использовать этот вид недостатка с плохой точки зрения. Этот тип уязвимости безопасности называется атакой с использованием межсайтовых сценариев (XSS).
Чтобы избежать этой проблемы, у вас есть два варианта:
По умолчанию в Django каждый шаблон автоматически экранирует результат каждого тега переменной. Точнее, эти пять символов экранированы:
Мы повторяем здесь, что это поведение активно по умолчанию. Если вы используете систему шаблонов Django, вы защищены.
Как отключить автоматическое экранирование ¶
Если вы не хотите, чтобы данные экранировались автоматически на уровне сайта, шаблона или переменной, вы можете отключить его несколькими способами.
Для отдельных переменных ¶
Чтобы отключить автоматическое экранирование для отдельной переменной, используйте фильтр safe :
Для шаблонных блоков ¶
Тег autoescape принимает on или off в качестве параметра. Иногда желательно принудительное автоматическое экранирование в контексте, где оно отключено. Вот пример шаблона:
Поскольку автоматическое экранирование отключено в базовом шаблоне, оно также будет отключено в дочернем шаблоне, в результате чего, например, будет отображаться следующий HTML-контент, когда переменная greeting содержит текст Hello! :
Примечания ¶
Обычно разработчикам шаблонов не нужно беспокоиться об автоматическом экранировании. Разработчики на стороне Python (те, кто пишет представления и настраиваемые фильтры) должны подумать о ситуациях, когда данные не следует экранировать, и пометить данные соответствующим образом, чтобы все работало так, как ожидалось в шаблонах.
Если вы создаете шаблон, который можно использовать в ситуациях, когда вы не уверены, активно ли автоматическое экранирование, добавьте фильтр escape к любой переменной, требующей экранирования. Когда активен автоматический переход, нет риска, что фильтр удвоит данные, потому что он не затрагивает переменные, которые уже прошли автоматический переход. escape
Буквальный текст и автоматическое экранирование ¶
Как упоминалось ранее, параметры фильтра могут быть строками:
Это означает, что вам нужно написать:
Это не влияет на данные, поступающие от самой переменной. При необходимости содержимое переменной всегда экранируется автоматически, поскольку оно находится вне контроля автора шаблона.
Доступ к вызовам методов ¶
Большинство вызовов методов, связанных с объектами, также доступны из шаблонов. Это означает, что шаблоны не только имеют доступ к атрибутам класса (например, именам полей) или переменным, передаваемым из представлений. Например, ORM Django предлагает синтаксис entry_set для получения коллекции объектов, связанных внешним ключом. Итак, учитывая модель «комментариев» с отношением внешнего ключа к модели «задачи», вы можете просмотреть все комментарии, относящиеся к данной задаче, следующим образом:
Точно так же объекты QuerySets предоставляют метод count() для подсчета количества содержащихся в них объектов. Таким образом, вы можете получить количество всех комментариев, относящихся к текущей задаче, с помощью:
Вы также можете получить доступ к методам, которые вы явно определили в своих собственных моделях:
Django передача параметров в шаблон
Функции-представления могут принимать параметры, через которые могут передаваться различные данные. Подобный параметры передаются в в адресе URL. Например, в запросе http://localhost/index/3/5/ поледние два сегмента 3/5/ могут представлять параметры URL, которые могут быть связанны с параметрами функции-представления через систему маршрутизации.
Определение параметров через функцию re_path
Определим в приложении в файле views.py следующие функции:
Во втором шаблоне адреса определяются два параметра: id и name ( (?P \d+)/(?P \D+) ). При этом параметр id должен представлять число, а параметр name должен состоять только из буквенных символов.
Ну и также отметим, что количество и название параметров в шаблонах адресов URL соответствуют количеству и названиям параметров соответствующих функций, которые обрабатывают запросы по данным адресам.
Теперь мы можем чем адресную строку передать данные в приложение:

Однако, что если мы не передадим значение для параметра или передадим ему значение, которое не соответствует регулярному выражению? В этом случае система не смодет найти ресурс для обработки запроса:
В этом случае мы можем определить в файле views.py для параметра функции products значение параметра по умолчанию:
То есть если в функцию не передается значение для параметра productid, то он получает значение 21.
В этом случае надо дополнительно определить еще один маршрут в файле urls.py :
Определение параметров через функцию path
Возьмем те же функции в файле views.py :
Определение параметров с помощью функции path() будет выглядеть следующим образом:
По умолчанию Django предоставляет следующие спецификаторы:
str : соответствует любой строке за исключенем символа «/». Если спецификатор не указан, то используется по умолчанию
int : соответствует любому положительному числу
slug : соответствует последовательности буквенных символов ASCII, цифр, дефиса и символа подчеркивания, например, building-your-1st-django-site
uuid : сооветствует идентификатору UUID, например, 075194d3-6885-417e-a8a8-6c931e272f00
path : соответствует любой строке, которая также может включать символ «/» в отличие от спецификатора str
Значения для параметров по умолчанию
Определеним для функций в views.py значения для параметров по умолчанию:
В этом случае для каждой функции надо определить по два маршрута:
Шаблоны¶
Проект Django можно настроить с одним или несколькими шаблонизаторами (или даже с нулем, если вы не используете шаблоны). Django предоставляет встроенные серверные модули для собственной системы шаблонов, творчески названной языком шаблонов Django (DTL), и для популярной альтернативы Jinja2. Серверные программы для других языков шаблонов могут быть доступны у третьих лиц. Вы также можете написать свой собственный бэкэнд, смотрите Пользовательский бэкэнд
Django определяет стандартный API для загрузки и рендеринга шаблонов независимо от серверной части. Загрузка состоит из поиска шаблона для данного идентификатора и его предварительной обработки, обычно компилируя его в представление в памяти. Рендеринг означает интерполяцию шаблона с помощью контекстных данных и возврат результирующей строки.
Система шаблонов небезопасна от ненадежных авторов шаблонов. Например, сайт не должен позволять своим пользователям предоставлять свои собственные шаблоны, поскольку авторы шаблонов могут выполнять такие действия, как выполнение XSS-атак и доступ к свойствам переменных шаблона, которые могут содержать конфиденциальную информацию.
Язык шаблонов Django¶
Синтаксис¶
Шаблон отображается с контекстом. Визуализация заменяет переменные их значениями, которые просматриваются в контексте, и выполняет теги. Все остальное выводится как есть.
Синтаксис языка шаблонов Django включает четыре конструкции.
Переменные¶
Переменная выводит значение из контекста, которое представляет собой dict-подобный объект, отображающий ключи к значениям.
Поиск по словарю, поиск по атрибутам и поиск по списку-индексу реализованы с использованием точечной нотации:
Если переменная преобразуется в вызываемую, система шаблонов вызовет ее без аргументов и будет использовать ее результат вместо вызываемого.
Теги обеспечивают произвольную логику в процессе рендеринга.
Это определение заведомо расплывчатое. Например, тег может выводить контент, служить структурой управления, например. оператор «if» или цикл «for», захват содержимого из базы данных или даже разрешение доступа к другим тегам шаблона.
Теги заключаются в символы <% и %>, например:
Большинство тегов принимают аргументы:
Для некоторых тегов требуются начальные и конечные теги:
Фильтры¶
Фильтры преобразуют значения переменных и аргументов тегов.



























