如何在Django模板if语句中使用TextChoices字段而不硬编码
在Django模板中使用模型的TextChoices常量做判断
给定如下Django模型:
class Foo(models.Model): class FooTypes(models.TextChoices): OK = "F", "Ok" BAR = "B", "FooBared!" foo_type = models.CharField(max_length=1, choices=FooTypes.choices)
想要在模板的if语句里直接用FooTypes.OK或FooTypes.BAR这类常量做判断,而非硬编码'F'或'B'这类数据库存储值,比如期望写出这样的模板代码:
{% if item.foo_type == FooTypes.OK %} ... {% endif %}
以下是几种可行的实现方式:
方法一:将TextChoices类传入模板上下文
在视图函数或类视图中,把Foo.FooTypes添加到模板的上下文字典里,让模板能直接访问到这个类:
# 函数视图示例 def foo_list(request): items = Foo.objects.all() return render(request, 'foo_list.html', { 'items': items, 'FooTypes': Foo.FooTypes # 传入TextChoices类 }) # 类视图示例(以ListView为例) class FooListView(ListView): model = Foo template_name = 'foo_list.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['FooTypes'] = Foo.FooTypes return context
之后在模板里,通过FooTypes.OK.value获取数据库存储的对应值,就能完成判断:
{% if item.foo_type == FooTypes.OK.value %} 这是OK类型的Foo {% elif item.foo_type == FooTypes.BAR.value %} 这是BAR类型的Foo {% endif %}
注:
FooTypes.OK是一个Choice实例,.value属性对应数据库中存储的"F",.label则是显示用的"Ok"。
方法二:给模型添加判断方法(更简洁)
把判断逻辑封装到模型的方法里,模板直接调用方法即可,代码可读性更高:
class Foo(models.Model): class FooTypes(models.TextChoices): OK = "F", "Ok" BAR = "B", "FooBared!" foo_type = models.CharField(max_length=1, choices=FooTypes.choices) def is_ok_type(self): return self.foo_type == self.FooTypes.OK.value def is_bar_type(self): return self.foo_type == self.FooTypes.BAR.value
模板里的写法会更干净:
{% if item.is_ok_type %} 这是OK类型的Foo {% elif item.is_bar_type %} 这是BAR类型的Foo {% endif %}
方法三:自定义模板标签(进阶场景)
如果多个模板都需要用到这类判断,可以自定义模板标签来简化操作,但前两种方法已经能覆盖大部分日常场景,这里仅提供思路:
- 在对应app下创建
templatetags目录,编写自定义过滤器或标签,实现Choice值的判断逻辑。 - 在模板中加载标签后直接使用,比如
{% load foo_tags %},再通过{% if item.foo_type == foo_types_ok %}完成判断。
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

