Django 模板 - 检查字段中是不是有值,如果 ManyToManyField 则为空
Posted
技术标签:
【中文标题】Django 模板 - 检查字段中是不是有值,如果 ManyToManyField 则为空【英文标题】:Django template - check if field has value in it or empty if ManyToManyFieldDjango 模板 - 检查字段中是否有值,如果 ManyToManyField 则为空 【发布时间】:2017-10-08 22:22:17 【问题描述】:这看起来很简单,但我无法从 SO 或 Django 文档(使用 Django 1.10)中找到一个好的解决方案
我正在获取模板中的模型对象并仅显示那些具有值(即非空白或空值)或在 ManyToManyField 时不为空的字段。
除了使用许多if
和else
来检查字段类型然后运行相应的if
条件之外,我无法找到一个好的方法。
% if model_name.field_name %
总是为ManytoManyField
s 返回true
(因为它是ManyRelatedManager
)
% if model_name.field_name|length > 0 %
总是为ManytoManyField
s 返回false
% if model_name.field_name.all %
可能适用于 ManyToManyFields
,但不适用于其他人(例如 CharField
)
是否有一种方法可以检查字段中是否有一些可用的值(无论是ManytoManyField
还是简单的CharField
)?我可以诉诸于使用多个if-else
首先检查字段类型,然后运行相应的检查,但这样做感觉违反直觉,因为这感觉像是证明模板标签的常见用例。
【问题讨论】:
如果你需要这样的逻辑,也许最好把它放到你的views.py
中。来自 ManyToManyField 或 ForeignKeyField 的关联对象应该使用相关管理器的某些方法调用:all
,或者可能是 filter
。
@cezar - 谢谢,我把逻辑移到了views.py。发布了我的最终代码作为答案。
【参考方案1】:
这就是我最终做的:
@cezar 的建议是有道理的,所以我将逻辑移至 views.py
(毕竟,是否显示值的逻辑将落入显示内容桶中,因此转到视图而不是如何在模板中显示)
此外,现在不是将模型对象返回到模板,而是返回一个仅包含相关值的字典。 ManyToManyFields(如果不为空)在字典中显示为列表。
for field in school._meta.get_fields(): # where school is the model object
#checking if field type is m2m
if (field.get_internal_type() == 'ManyToManyField'):
if getattr(school,field.name).exists():
school_display[field.name] = [k.name for k in getattr(school, field.name).all()]
#checking if field has choices (so we could send the display name)
elif field.choices:
func_name_to_display = 'get_' + field.name + '_display'
#note the '()' at the end, below. getattr(a,b) is equivalent to a.b so we need to add a '()' at the end since its a function
school_display[field.name] = getattr(school,func_name_to_display)()
#just returning the value (if not empty) in other cases
else:
field_value = getattr(school,field.name)
if (field_value and field_value!='None'):
school_display[field.name] = field_value
return render(request, 'detail.html', 'school_display' : school_display)
我很高兴我这样做了,因为在此过程中,我发现在模型对象上调用了理想情况下属于 views.py 的另外两个方法,并且也移动了它们。
很高兴了解上述方法是否可以改进。
【讨论】:
【参考方案2】:如果你使用模板过滤器,它应该是什么样子的会很明显:
from django import template
register = template.Library()
@register.filter
def is_not_empty(field):
try:
return field.count()
except (AttributeError, TypeError):
return field
【讨论】:
【参考方案3】:您可以使用 get_fields
: https://docs.djangoproject.com/en/1.11/ref/models/meta/#retrieving-all-field-instances-of-a-model 使其更清洁
所以在你的情况下,它看起来像这样(这是伪代码):
% for field in Model._meta.get_fields() %
% if field.get_internal_type() == "ManyToManyField" %
... # render m2m, here you could use gettatr
% else %
... # render regular field, here you could use gettatr
% endif %
% endfor %
但我也同意@cezar 的评论,即您应该将此类内容移至views.py
【讨论】:
谢谢@Sardorbek - 你的意思是在模板中以某种方式使用 get_fields()、getattr()、get_internal_type() 等的相应逻辑吗?我已经发布了我的代码 - 现在将逻辑移至views.py,有趣的是,最终代码看起来类似于您的模板伪代码,因此赞成 @Anupam 是的,它可以在模板中使用,但我强烈建议您在 views.py 中这样做。以上是关于Django 模板 - 检查字段中是不是有值,如果 ManyToManyField 则为空的主要内容,如果未能解决你的问题,请参考以下文章
检查/验证 Django 模板中是不是有小数位实数,如果为零,则四舍五入