Ох этот скромный {% if %}. Краеугольный камень шаблоной логики Django.
Каждый, кто начинал работать с Django 1.1 (или ранее), почти наверняка спотыкался об этот камень — шаблонный тег Django {% 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 %}.
Шаблоны Django - всё-таки не Python
Запомните: шаблоны Django — это всё-таки не Python. У вас нет доступа к ключевому слову None или встроенным python функциям. {% if movie == None %} не сработает так, как вы этого хотите. Но если вам не достаточно {% if not movie %}, вы определённо делаете что-то не так.
Сложная булева логика
Также тег теперь поддерживает одновременное использование and и or. Но я бы не советовал вам часто пользоваться этой возможностью, т.к. она частенько ведёт к путанице. Например:
{% if staff or author and not expired %}
{% 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) с описанием парсера под названием .
Также сниппет был в некоторой степени наивен при разборе сложных логических выражений. Например, «A or B and C» парсилось как "(A or B) and C", а не как в Python «A or (B and C)».
Улучшенная же реализация парсера и была отправлена в качестве патча. В итоге, парсер взвешивает операторы в том же порядке, что и Python (от низшего приоритета к высшему):
- or
- and
- not
- in
- сравнения (==, !=, <, >, <=, >=)
Много свободного времени?
Прочитайте пару раз статью , попытайтесь понять, что там происходит, а потом… напишите свой собственный парсер.
Если нужно, можете снова подглядеть в статью, но интерес в том, чтобы переписать функционал, поняв идею, а не просто стащить готовую реализацию.
Будучи мазохистом со стажем, я попытался сделать это, прочитав только первый параграф. .
Только потому что вы можете…
Не стоит бросаться и пихать во все шаблоны логику и сравнения. Разделяйте вашу бизнес логику и представление. Быть может, стоит сравнение перенести во view или даже в метод модели?
О важности разделения логики и представления было сказано и написано уже много слов, но вот ещё пара причин.
Верстальщики — не программисты
Отсутствие логики в шаблонах позволит верстальщикам сосредоточиться на том, что они делают хорошо, а не на разбор таких вещей, как приоритет операторов сложной булевой логики.
Читаемость
Намного удобнее читать код бизнес логики без примесей шаблонного кода, точно так же, как и читать html код без мыслей о логике безопасности и структуре базы данных.
endif
Я могу бесконечно болтать о функционале и логике нового тега, так что давайте уже остановимся.
На последок хочется поблагодарить Luke Plant за его работу по подготовке всего этого дела к релизу в Django 1.2.
И, конечно же, не забудьте заглянуть в официальную документацию, где написано всё о возможностях нового .
Добавить комментарий