How to use multiple arguments in an if statement with Liquid - if-statement

I want to use an if statement in Liquid with multiple conditionals. Something like:
{% if (include.featured == "true" and product.featured == "true") or (include.featured == "false" and product.featured == "false") %}
Multiple conditionals don't seem to work. Have I got the syntax wrong or can Liquid not handle this sort of if statement?

Unfortunately, Liquid has a poor implementation of boolean algebra.
Using Liquid's operators and tags, here is a dirty way to achieve it:
{% if include.featured == true and product.featured == true %}
{% assign test = true %}
{% endif %}
{% if include.featured == false and product.featured == false %}
{% assign test = true %}
{% endif %}
{% if test %}
Yepeeee!
{% endif %}

Another way you can condense this is to combine else if statements, and booleans don't necessarily need the "==" when evaluating true:
{% if include.featured and product.featured %}
{% assign test = true %}
{% elsif include.featured == false and product.featured == false %}
{% assign test = false %}
{% endif %}

Related

Is there a way to use a flag variable in a template?

I'm looping through a result set and when a certain condition is met I want to run through a conditional statement. After that condition has been met I want to continue looping through the result set without running through that condition.
Does anyone have any ideas on how I could go about this?
Edit:
Here is what I'm trying to achieve.
{% flag = false %}
{% for row in results %}
{{ row.field }}
{% if row.is_active and !flag %}
<br />
{% flag = true %}
{% endif %}
{% endfor %}
It seems that you want to do one thing with the first part of the QuerySet, and other thing with the rest. Split it in the view.
views.py
def split_list(list, condition):
list1, list2 = [], []
condition_satisfied = False
for element in list:
if not condition_satisfied and condition(element):
condition_satisfied = True
if not condition_satisfied:
list1.append(element)
else:
list2.append(element)
return list1, list2
def your_view(request):
results = YourModel.objects.all()
results1, results2 = split_list(results, condition)
return render(request, 'template.html', {
'results1': results1,
'results2': results2
})
template.html
{% for result in results1 %}
{% if result == whatever %}
<p>Condition satisfied</p>
{% else %}
<p>Condition not satisfied</p>
{% endif %}
{% endfor %}
{% for result in results2 %}
{{ result }}
{% endfor %}
Django doesn't have this feature, and for good reason. Templates should not contain this kind of logic. It should be done within the View.

writing the ladder if equality statements in django

I know i can do this in django template
ifequal "this"
...//
else
...//
endifequal
but how do i write this
ifequal "this"
..//
elseifequal "this"
...//
else
....
is there a elegant way to achieve this in django ?
Django templates support the Python-like elif tag. For example:
{% if this == True %}
Yes!
{% elif this == False %}
No!
{% else %}
What?
{% endif %}
Source: https://docs.djangoproject.com/en/dev/ref/templates/builtins/#if
The documentation is very easy to find, so I suggest you read up on that.
try this,
{% ifequal p.gender "M" %}
Bloke
{% else %}
Sheila
{% endifequal %}
The ifequal tag determines if two arguments are equal. The arguments can be either
variables or hard-coded strings. If the arguments match, the template engine renders the
code inside the ifequal block. You need to add an endifequal tag to end the block.
https://docs.djangoproject.com/en/1.6/ref/templates/builtins/#ifequal

Template filter common Q of if equal True

I assign 'result':True and passed it to template.
For template file, I write
{{ result }}
{% if result == True %}
this also True
{% endif %}
{% if result == 1 %}
this is 1
{% endif %}
{% if result == true %}
this is true
{% endif %}
Result is,
' True this is 1 '
I think 'Trthis also True
As #PepperoniPizza mentions in the comments above, in Python it's not recommended to compare values to True or False using ==. Most of the time, you only need to use {% if result %} in your template -- it doesn't matter whether result is True, 1, or some other value than evaluates to True.
If you really need to do {% if result == True %}, this will work in Django 1.5. From the release notes:
The template engine now interprets True, False and None as the corresponding Python objects.

Django TemplateSyntax: Two tests with an 'If .. or...'

I am trying to run two tests:
{% if profile.id != 100 or profile.location == NULL %}
however it seems to not work. I couldn't find in the docs why this isn't working. Any ideas?
EDIT:
In the SQL db, the value for profile.location is NULL. The rendered result is None.
EDIT 2:
Here is the full chain. There are 4 ways to grab a user's location. It is a giant mess as you can see...
{% if profile.city.id != 104 or profile.city %}
{{profile.city}}
{% else %}
{% if profile.mylocation != '' %}
{{ profile.mylocation }}
{% else %}
{% if profile.fbconnect == 1 and profile.location != '' and profile.location != "None" %}
{{profile.location}}
{% else %}
{% if profile.sglocation.city %}{{profile.sglocation.city}}{% else %}{{profile.sglocation.country}}{% endif %}
{% endif %}
{% endif %}
{% endif %}
There's no NULL. Try:
{% if profile.id != 100 or not profile.location %}
If I were you, I would throw all that logic back into Python, for example:
class Profile(models.Model):
[your model fields and stuff]
def get_location(self):
[your location logic]
Then in the template you can just do:
{{ profile.get_location }}

Django templates: If false?

How do I check if a variable is False using Django template syntax?
{% if myvar == False %}
Doesn't seem to work.
Note that I very specifically want to check if it has the Python value False. This variable could be an empty array too, which is not what I want to check for.
For posterity, I have a few NullBooleanFields and here's what I do:
To check if it's True:
{% if variable %}True{% endif %}
To check if it's False (note this works because there's only 3 values -- True/False/None):
{% if variable != None %}False{% endif %}
To check if it's None:
{% if variable == None %}None{% endif %}
I'm not sure why, but I can't do variable == False, but I can do variable == None.
Django 1.10 (release notes) added the is and is not comparison operators to the if tag. This change makes identity testing in a template pretty straightforward.
In[2]: from django.template import Context, Template
In[3]: context = Context({"somevar": False, "zero": 0})
In[4]: compare_false = Template("{% if somevar is False %}is false{% endif %}")
In[5]: compare_false.render(context)
Out[5]: u'is false'
In[6]: compare_zero = Template("{% if zero is not False %}not false{% endif %}")
In[7]: compare_zero.render(context)
Out[7]: u'not false'
If You are using an older Django then as of version 1.5 (release notes) the template engine interprets True, False and None as the corresponding Python objects.
In[2]: from django.template import Context, Template
In[3]: context = Context({"is_true": True, "is_false": False,
"is_none": None, "zero": 0})
In[4]: compare_true = Template("{% if is_true == True %}true{% endif %}")
In[5]: compare_true.render(context)
Out[5]: u'true'
In[6]: compare_false = Template("{% if is_false == False %}false{% endif %}")
In[7]: compare_false.render(context)
Out[7]: u'false'
In[8]: compare_none = Template("{% if is_none == None %}none{% endif %}")
In[9]: compare_none.render(context)
Out[9]: u'none'
Although it does not work the way one might expect.
In[10]: compare_zero = Template("{% if zero == False %}0 == False{% endif %}")
In[11]: compare_zero.render(context)
Out[11]: u'0 == False'
I think this will work for you:
{% if not myvar %}
You could write a custom template filter to do this in a half-dozen lines of code:
from django.template import Library
register = Library()
#register.filter
def is_false(arg):
return arg is False
Then in your template:
{% if myvar|is_false %}...{% endif %}
Of course, you could make that template tag much more generic... but this suits your needs specifically ;-)
In old version you can only use the ifequal or ifnotequal
{% ifequal YourVariable ExpectValue %}
# Do something here.
{% endifequal %}
Example:
{% ifequal userid 1 %}
Hello No.1
{% endifequal %}
{% ifnotequal username 'django' %}
You are not django!
{% else %}
Hi django!
{% endifnotequal %}
As in the if tag, an {% else %} clause is optional.
The arguments can be hard-coded strings, so the following is valid:
{% ifequal user.username "adrian" %}
...
{% endifequal %}
An alternative to the ifequal tag is to use the if tag and the == operator.
ifnotequal
Just like ifequal, except it tests that the two arguments are not equal.
An alternative to the ifnotequal tag is to use the if tag and the != operator.
However, now we can use if/else easily
{% if somevar >= 1 %}
{% endif %}
{% if "bc" in "abcdef" %}
This appears since "bc" is a substring of "abcdef"
{% endif %}
Complex expressions
All of the above can be combined to form complex expressions. For such expressions, it can be important to know how the operators are grouped when the expression is evaluated - that is, the precedence rules. The precedence of the operators, from lowest to highest, is as follows:
or
and
not
in
==, !=, <, >, <=, >=
More detail
https://docs.djangoproject.com/en/dev/ref/templates/builtins/
Just ran into this again (certain I had before and came up with a less-than-satisfying solution).
For a tri-state boolean semantic (for example, using models.NullBooleanField), this works well:
{% if test.passed|lower == 'false' %} ... {% endif %}
Or if you prefer getting excited over the whole thing...
{% if test.passed|upper == 'FALSE' %} ... {% endif %}
Either way, this handles the special condition where you don't care about the None (evaluating to False in the if block) or True case.
I have had this issue before, which I solved by nested if statements first checking for none type separately.
{% if object.some_bool == None %}Empty
{% else %}{% if not object.some_bool %}False{% else %}True{% endif %}{% endif %}
If you only want to test if its false, then just
{% if some_bool == None %}{% else %}{% if not some_bool %}False{% endif %}{% endif %}
EDIT: This seems to work.
{% if 0 == a|length %}Zero-length array{% else %}{% if a == None %}None type{% else %}{% if not a %}False type{% else %}True-type {% endif %}{% endif %}{% endif %}
Now zero-length arrays are recognized as such; None types as None types; falses as False; Trues as trues; strings/arrays above length 0 as true.
You could also include in the Context a variable false_list = [False,] and then do
{% if some_bool in false_list %}False {% endif %}
Look at the yesno helper
Eg:
{{ myValue|yesno:"itwasTrue,itWasFalse,itWasNone" }}
I've just come up with the following which is looking good in Django 1.8
Try this instead of value is not False:
if value|stringformat:'r' != 'False'
Try this instead of value is True:
if value|stringformat:'r' == 'True'
unless you've been really messing with repr methods to make value look like a boolean I reckon this should give you a firm enough assurance that value is True or False.
This is far easier to check in Python (i.e. your view code) than in the template, because the Python code is simply:
myvar is False
Illustrating:
>>> False is False
True
>>> None is False
False
>>> [] is False
False
The problem at the template level is that the template if doesn't parse is (though it does parse in). Also, if you don't mind it, you could try to patch support for is into the template engine; base it on the code for ==.
you can use the int value of true and false
True = any int
False = zero
so, if we take an example:
{% if user.is_authenticated == 1 %}
do something
{% endif %}
this mean in python
if user.is_authenticated:
#do something
and
{% if user.is_authenticated == 0 %}
do something
{% endif %}
this mean in python
if not user.is_authenticated :
#do something
OR equal
if !(user.is_authenticated) :
#do something
OR equal
if user.is_authenticated == False :
#do something
It can be done:if you use "select" tag.
{% if service.active == 0 %} selected {% endif%}