如何在Django模板中检查变量是否为“False”?

85

如何使用Django模板语法检查变量是否为False

{% if myvar == False %}

似乎不起作用。

请注意,我非常明确地想检查它是否具有Python值False。这个变量也可能是一个空数组,但这不是我想要检查的。


在模板上下文中拥有一个既可以是列表又可以是布尔值的变量似乎从一开始就是错误的方法? - Risadinha
@Risadinha 我不记得我的用例了。你可能是对的。 - mpen
1
{% if not myvar%} 这在 Django 1.11 中肯定有效,但我不确定你能回溯到多远! - Ibo
@Ibo 我很确定 not myvar 检查的是 myvar 是否为 falsey,而不是 False参见 - mpen
@mpen 所以如果 myvar 是一个布尔值,无论它的值是真还是假,如果它被作为上下文变量通过渲染函数传递到模板中,则 not myvar 将返回 True?在这种情况下,应该检查两件事:1-是否向渲染函数提供了 myvar,2-如果提供了 myvar,则其具有什么值。如果 myvar 更像是类实例、字典、对象等而不是经典变量,则这将变得相当复杂。 - Ibo
13个回答

51

为了后人的参考,我有一些NullBooleanField,这是我的操作:

要检查它是否为True


要检查它是否为 True:
{% if variable %}True{% endif %}

要检查它是否为False(请注意,这适用于只有三个值的情况——True/False/None):


To check if it's False (note this works because there's only 3 values -- True/False/None):
{% if variable != None %}False{% endif %}

检查它是否为None

{% if variable == None %}None{% endif %}

我不确定为什么,但我不能使用variable == False,但是我可以使用variable == None


1
一个更好的惯用语(由 PEP 8 推荐),用于检查 None 的方法是使用 is,因为 None 是单例。比较时应该始终使用 isis not,而不是等于运算符。 - Humphrey Bogart
21
@Beau: Django模板不是Python代码。模板条件表达式中没有“is”运算符。 - Ville Laurikari
这应该在某本书中。很多人使用 models.NullBooleanField() - Robert Johnstone

44

Django 1.10 (发布说明) 增加了 if 标签中的比较运算符 isis not。这一改动使模板中的标识测试更加简单直观。

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'

如果您使用的是旧版本Django,则从1.5版本开始,模板引擎会将TrueFalseNone解释为相应的Python对象。详情请见发行说明

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'

虽然它的工作方式与人们可能预期的不同。

In[10]: compare_zero = Template("{% if zero == False %}0 == False{% endif %}")
In[11]: compare_zero.render(context)
Out[11]: u'0 == False'

1
将其接受以使其置于顶部,其他使用当前版本的人可以找到它 :-) - mpen
当我的上下文变量包含整数0(零)时,我遇到了一个问题。当它被Django渲染时,它被解释为“False”。因此,看起来我仍然需要像Gabriel Hurley建议的自定义模板标签。 - ceasaro
你可以明确地检查变量是否为0,但是模板标签可能更简洁。 - Martin

43

我认为这个方案适合你:

{% if not myvar %}

13
这个问题明确提到只检查False值,不应该由空数组触发。这适用于两者。 - Shawn Chin

23
你可以编写一个自定义模板过滤器来完成这个任务,只需几行代码即可:
from django.template import Library

register = Library()

@register.filter
def is_false(arg): 
    return arg is False

然后在你的模板中:

{% if myvar|is_false %}...{% endif %}

当然,你可以使该模板标签更加通用化... 但这特别适合满足你的需求 ;-)


2
不知道你可以在 ifs 中使用过滤器。很酷 :) 实际上,我通过将“None”作为我的假值来回避这个问题,但是以后参考起来很好知道。 - mpen
我每天都尽力学习新东西...很高兴能分享;-) - Gabriel Hurley

10

在旧版本中,你只能使用ifequalifnotequal

{% ifequal YourVariable ExpectValue %}
    # Do something here.
{% endifequal %}

示例:

{% ifequal userid 1 %}
  Hello No.1
{% endifequal %}

{% ifnotequal username 'django' %}
  You are not django!
{% else %}
  Hi django!
{% endifnotequal %}
与 if 标签一样,{% else %}子句是可选的。
参数可以是硬编码字符串,所以下面的代码是有效的:
{% ifequal user.username "adrian" %} ... {% endifequal %}
ifequal 标签的替代方法是使用 if 标签和 == 运算符。
ifnotequal 与 ifequal 类似,但它测试两个参数是否不相等。
ifnotequal 标签的替代方法是使用 if 标签和 != 运算符。
然而,现在我们可以轻松地使用 if/else。
{% if somevar >= 1 %}
{% endif %}

{% if "bc" in "abcdef" %}
  This appears since "bc" is a substring of "abcdef"
{% endif %}

复杂表达式

上述所有内容可以组合成复杂表达式。对于这种表达式,了解运算符在表达式求值时的分组方式即优先级规则非常重要。运算符的优先级从低到高分别是:

  • or
  • and
  • not
  • in
  • ==, !=, <, >, <=, >=

更多细节

https://docs.djangoproject.com/en/dev/ref/templates/builtins/


3
我看不到任何提到检查 False 的内容。现在,False 是一个支持的关键字吗? - mpen

6

我再次遇到了这个问题(确定之前遇到过,但找到的解决方案不是很令人满意)。

对于三态布尔类型(例如使用models.NullBooleanField),以下代码可行:

{% if test.passed|lower == 'false' %} ... {% endif %}

如果您喜欢对整个事情感到兴奋...

{% if test.passed|upper == 'FALSE' %} ... {% endif %}

无论哪种情况,这都处理了特殊条件,即您不关心 None (在if块中计算为False)或 True 情况。


完美地处理布尔字段!谢谢! - JDavies

4

我之前也遇到过这个问题,我通过嵌套if语句并首先单独检查none类型来解决它。

{% if object.some_bool == None %}Empty
{% else %}{% if not object.some_bool %}False{% else %}True{% endif %}{% endif %}

如果你只想测试它是否为假,那么只需这样:
{% if some_bool == None %}{% else %}{% if not some_bool %}False{% endif %}{% endif %}

编辑:这似乎有效。

{% 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 %}

现在零长度的数组被认为是零长度的数组;None类型作为None类型;falses作为False;Trues作为true;长度大于0的字符串/数组作为true。

你还可以在上下文中包含一个变量false_list = [False,],然后进行以下操作

{% if some_bool in false_list %}False {% endif %}

1
这个区分了NoneFalse但没有[],它也是假的。 - mpen
我正在处理一个始终为NullBooleanField(None/True/False)的变量的渲染。我相信你可以以同样的方式扩展它,例如:{% if some_bool == [] %}{% else %} ... 但此时看起来非常丑陋,可能值得编写自己的模板标签。http://docs.djangoproject.com/en/dev/howto/custom-template-tags/ - dr jimbob
它甚至不认识[]吗?它也不认识False。很遗憾我得自己写模板标签来解决这个问题:\ - mpen
@Mark,请查看上面的编辑;你可以使用{% if 0 == a|length %}代替{% if some_bool == [] %}。实际测试过,结果符合预期。 - dr jimbob
不错的编辑...那确实是一种方法。看起来相当糟糕 :) 我认为一个新的模板标签会是较小的恶。 - mpen

4

请查看yesno辅助工具

例如:

{{ myValue|yesno:"itwasTrue,itWasFalse,itWasNone" }}

不对。我想要放一个完整的代码块进去,而不仅仅是一个简单的字符串。 - mpen

3
我刚想出以下代码,在Django 1.8中看起来不错:
尝试使用以下代码代替value is not False:
if value|stringformat:'r' != 'False'

如果要判断变量的值为True,可以尝试使用以下方法:

if value|stringformat:'r' == 'True'

除非您一直在破坏repr方法,使值看起来像布尔值,否则我认为这应该可以给您足够的保证,即value是True或False。


2

这在Python中(即您的视图代码)要比在模板中更容易检查,因为Python代码只需:

myvar is False

说明:

>>> False is False
True
>>> None is False
False
>>> [] is False
False

模板层面的问题在于模板中的if语句不支持is关键字(但支持in关键字)。如果您不介意,可以尝试修改模板引擎以支持is关键字,可以参考==关键字的代码实现。

== False 也可以正常工作。我们不需要 is,我们只需要它将 False 识别为关键字。我想按照您的建议在视图中完成这项任务最容易,但是......让所有这些一次性布尔值混乱在一起很烦人。 - mpen
1
"myvar is False" 违反了 PEP-8 规范;正确的方式是使用 "not myvar"。 - ThiefMaster
但是在这种情况下,== 不是以相同的方式工作吗?
False == False #(True) None == False #(False) [] == False #(False)
- dr jimbob
@ThiefMaster:但它不一定是布尔值。它可以是布尔值或列表。因此,区分它们是必要的。 - mpen
"0 is False" 是错误的,"0 == False" 是正确的 - 所以如果你不确定你的变量是布尔类型,使用 "is" 可能不是你想要的。 - ThiefMaster
@ThiefMaster:Mark特别强调说,“请注意,我非常明确地想要检查它是否具有Python值False。这个变量也可能是一个空数组,这不是我想要检查的。” 这就导致了我上面的示例,其中is是解决问题的最简单的方法。 - Mike DeSimone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接