Django模板中基于字段值的if条件判断失效问题排查
Django模板中外键字段判断错误的问题分析与解决
问题描述
模型定义如下:
class Book(models.Model): status = models.ForeignKey( 'BookStatus', verbose_name='Status', on_delete=models.RESTRICT, null=True, blank=True, )
class BookStatus(models.Model): name = models.CharField( max_length=50, unique=True, ) def __str__(self): """String for representing the Model object.""" return self.name
视图使用常规的DetailView:
class BookDetailView(LoginRequiredMixin, generic.DetailView): login_url = '/accounts/login/' model = Book
在详情页模板中尝试通过以下条件控制按钮显示:
{% if book.status != 'vorhanden' %} ... {% endif %}
即使书籍状态为vorhanden,条件仍成立;反向判断{% if book.status == 'vorhanden' %}时,即使状态匹配,条件也不生效。
错误原因
book.status是BookStatus模型的实例对象,不是字符串。直接将模型对象与字符串'vorhanden'做相等判断,两者类型完全不同,永远不会匹配,因此两个条件的结果都不符合预期。
解决方案
方案1:直接访问外键实例的name属性
直接获取外键对象的name字段值进行比较,同时注意处理status为null的场景(避免抛出属性不存在的错误):
{% if book.status and book.status.name != 'vorhanden' %} <!-- 你的按钮代码 --> {% endif %}
方案2:将模型实例转为字符串后比较
利用Django模板过滤器stringformat把模型实例转成字符串(依赖模型的__str__方法返回name值),同样要处理status为null的情况:
{% if book.status and book.status|stringformat:"s" != 'vorhanden' %} <!-- 你的按钮代码 --> {% endif %}
方案3:在视图中提前处理上下文变量
重写DetailView的get_context_data方法,提前计算好判断结果并传入模板,模板直接使用变量即可:
class BookDetailView(LoginRequiredMixin, generic.DetailView): login_url = '/accounts/login/' model = Book def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) book = self.get_object() # 提前计算判断结果,传入模板 context['is_not_vorhanden'] = book.status is not None and book.status.name != 'vorhanden' return context
模板中使用:
{% if is_not_vorhanden %} <!-- 你的按钮代码 --> {% endif %}
内容的提问来源于stack exchange,提问作者matkoh
相关产品推荐
相关产品推荐

