{% if %}. Краеугольный камень шаблоной логики Django.Каждый, кто начинал работать с Django 1.1 (или ранее), почти наверняка спотыкался об этот камень — шаблонный тег
{% if %} поддерживает булеву логику только на базовом уровне.Вообще, ограничение на работу тега только с переменной, которая имеет значение «true» (т.е. существует, не пустая и не ложь), было введено умышленно, чтобы подстрекать программистов разделять представление и логику.
Как-то раз я решил написать более гибкий и умный тег if. Посидев на выходных за клавиатурой, я опубликовал свой тег как сниппет, который очень скоро стал весьма популярным. А ещё восемь месяцев спустя была предложена замена тега if в Django 1.2.
Чего же нового, мистер If?
Начиная с Django 1.2 возможности
{% if %} были расширены до поддержки базовой питонячей логики, позволяя вам делать такие вещи: {% if you.friends.count > 5 %}Вы популярны!{% endif %}
{% if country != "NZ" %}Приезжайте к нам в Новую Зеландию.{% endif %} При этом вы всё ещё можете использовать фильтры. Таким образом, вы можете без проблем писать
{% if messages|length > 3 %}...{% endif %}.Всё-таки не Python
Запомните: шаблоны Django — это всё-таки не Python. У вас нет доступа к ключевому слову
None или встроенным python функциям. {% if movie == None %} не сработает так, как вы этого хотите. Но если вам не достаточно {% if not movie %}, вы определённо делаете что-то не так.Сложная булева логика
Также тег теперь поддерживает одновременное использование
and и or. Но я бы не советовал вам часто пользоваться этой возможностью, т.к. она частенько ведёт к путанице. Например: {% if staff or author and not expired %}
<a href="{{ edit_url }}">Edit this</a>
{% endif %} Дизайнерам может быть не понятно, что тут происходит («если пользователь принадлежит персоналу, но при этом время редактирования уже прошло, что будет?»). Было бы намного понятнее вычислить переменную can_edit во view и передать её в шаблон.
Если вам нужен порядок проверки условий, отличный от приоритета операций в Python, используйте несколько тегов if. Использование скобок не поддерживается.
Отсутствующие переменные
Важно помнить, что происходит, когда переменная не определена в контексте шаблона: её значение просто считается равным
None.Докопаемся до истины
Давайте посмотрим, что происходит там внутри (если вы не один из тех, кто любит ковыряться во внутренностях, можете пропустить эту часть).
В том самом сниппете парсер был совсем простой. Он работал, но не особо углубляясь в детали. Однако был в нём один значительный баг: операторы сравнения не имели превосходства над булевыми:
x or x == 0 парсилось как (x or x) == 0 вместо x or (x == 0). Хоть это и удалось пофиксить, я никогда не был доволен получившимся кодом, что замечали и другие, например, Рассел Кейт-Мэги (Russel Keith-Magee). Позже Люк Плэнт (Luke Plant) поделился ссылкой на статью Фредрика Ланда (Fredrik Lundh) с описанием парсера под названием Simple Top-down Parsing in Python.
Также сниппет был в некоторой степени наивен при разборе сложных логических выражений. Например, «A or B and C» парсилось как "(A or B) and C", а не как в Python «A or (B and C)».
Улучшенная же реализация парсера и была отправлена в качестве патча. В итоге, парсер взвешивает операторы в том же порядке, что и Python (от низшего приоритета к высшему):
- or
- and
- not
- in
- сравнения (==, !=, <, >, <=, >=)
Много свободного времени?
Прочитайте пару раз статью Simple Top-down Parsing in Python, попытайтесь понять, что там происходит, а потом… напишите свой собственный парсер.
Если нужно, можете снова подглядеть в статью, но интерес в том, чтобы переписать функционал, поняв идею, а не просто стащить готовую реализацию.
Будучи мазохистом со стажем, я попытался сделать это, прочитав только первый параграф. Вот что у меня получилось.
Только потому что вы можете…
Не стоит бросаться и пихать во все шаблоны логику и сравнения. Разделяйте вашу бизнес логику и представление. Быть может, стоит сравнение перенести во view или даже в метод модели?..
О важности разделения логики и представления было сказано и написано уже много слов, но вот ещё пара причин.
Верстальщики — не программисты
Отсутствие логики в шаблонах позволит верстальщикам сосредоточиться на том, что они делают хорошо, а не на разбор таких вещей, как приоритет операторов сложной булевой логики.
Читаемость
Намного удобнее читать код бизнес логики без примесей шаблонного кода, точно так же, как и читать html код без мыслей о логике безопасности и структуре базы данных.
endif
Я могу бесконечно болтать о функционале и логике нового тега, так что давайте уже остановимся.
Хочется поблагодарить Luke Plant за его работу по подготовке всего этого дела к релизу в Django 1.2.
И, конечно же, не забудьте заглянуть в официальную документацию, где написано всё о возможностях нового тега if.



комментарии (38)