Oh, that humble
{% if %}
. The cornerstone of the Django logic pattern.
Anyone who started working with Django 1.1 (or earlier) almost certainly stumbled over this stone - the template tag
{% if %}
supports the Boolean logic at a basic level.
In general, a restriction on tag operation with only a variable that has a value of “true” (that is, it exists, is not empty or false) was intentionally introduced to incite programmers to separate presentation and logic.
')
Once I decided to write a more flexible and smart if tag. After sitting at the weekend at the keyboard, I published my tag as a
snippet , which very soon became very popular. And eight months later, the replacement of the if tag in Django 1.2 was proposed.
What is new, Mr. If?
Starting with Django 1.2, the
{% if %}
features have been extended to support basic python logic, allowing you to do such things:
{% if you.friends.count > 5 %} ! {% endif %}
{% if country != "NZ" %} . {% endif %}
However, you can still use filters. Thus, you can easily write
{% if messages|length > 3 %}...{% endif %}
.
Still not Python
Remember: Django templates are not Python after all. You do not have access to the
None
keyword or python built-in functions.
{% if movie == None %}
does not work the way you want it. But if
{% if not movie %}
is not enough for you, you are definitely doing something wrong.
Complex Boolean Logic
Also, the tag now supports simultaneous use of
and
and
or
. But I would not advise you to use this opportunity often, because it often leads to confusion. For example:
{% if staff or author and not expired %}
<a href="{{ edit_url }}">Edit this</a>
{% endif %}
Designers may not understand what is happening here (“if the user belongs to the staff, but the editing time has already passed, what will happen?”). It would be much clearer to calculate the can_edit variable in the view and pass it to the template.
If you need a procedure for checking conditions other than the priority of operations in Python, use several if tags. The use of brackets is not supported.
Missing variables
It is important to remember what happens when a variable is not defined in the template context: its value is simply considered to be
None
.
Dig up the truth
Let's see what happens inside there (if you are not one of those who like to poke around in the inside, you can skip this part).
In that snippet, the parser was quite simple. He worked, but not really going into details. However, there was one significant bug in it: comparison operators did not have superiority over boolean ones:
x or x == 0
parsed as
(x or x) == 0
instead of
x or (x == 0)
.
Even though I managed to fix it, I was never happy with the resulting code that others noticed, for example, Russell Keith-Magee (Russel Keith-Magee). Later, Luke Plant (Luke Plant) shared a link to an article by Fredrik Lundh with a description of the parser called
Simple Top-down Parsing in Python .
Also, the snippet was somewhat naive when parsing complex logical expressions. For example, "A or B and C" was parsed as "(A or B) and C", and not like in Python "A or (B and C)".
The improved implementation of the parser was sent as a patch. As a result, the parser weights the operators in the same order as Python (from lowest priority to highest priority):
- or
- and
- not
- in
- comparisons (==,! =, <,>, <=,> =)
A lot of free time?
Read a couple of times the article
Simple Top-down Parsing in Python , try to understand what is happening there, and then ... write your own parser.
If necessary, you can peek into the article again, but the interest is in rewriting the functional, having understood the idea, and not just to steal the finished implementation.
Being an experienced masochist, I tried to do this by reading only the first paragraph.
That's what I did .
Just because you can ...
It is not necessary to rush and push logic and comparisons into all templates. Separate your business logic and presentation. Perhaps, it is worthwhile to transfer the comparison to the view or even to the model method? ..
Many words have been said and written about the importance of separating logic and representation, but here are a couple of reasons.
Layouts are not programmers.
The lack of logic in the templates will allow layout designers to focus on what they are doing well, and not on examining things like the priority of operators of complex Boolean logic.
Readability
It is much more convenient to read the business logic code without any impurities in the sample code, just like reading html code without thinking about the security logic and database structure.
endif
I can talk endlessly about the functionality and logic of the new tag, so let's stop now.
I would like to thank Luke Plant for his work in preparing the whole thing for release in Django 1.2.
And, of course, do not forget to look into the official documentation, where everything is written about the possibilities of the new
if tag .