Django模板-检查字段中是否有值,如果有ManyToManyField,则检查为空
这看起来相当简单,但我无法从SO或Django文档(使用Django 1.10)中找到一个好的解决方案 我正在获取模板中的模型对象,并仅显示那些具有值(即不为空或null)或不为空(如果为ManyToManyField)的字段 除了使用许多Django模板-检查字段中是否有值,如果有ManyToManyField,则检查为空,django,django-models,django-templates,django-template-filters,Django,Django Models,Django Templates,Django Template Filters,这看起来相当简单,但我无法从SO或Django文档(使用Django 1.10)中找到一个好的解决方案 我正在获取模板中的模型对象,并仅显示那些具有值(即不为空或null)或不为空(如果为ManyToManyField)的字段 除了使用许多if和else检查字段类型,然后运行相应的if条件外,我无法找到一个好方法来执行此操作 {%if model_name.field_name%}始终为ManytoManyFields返回true(因为它是ManyRelatedManager) {%if mod
if
和else
检查字段类型,然后运行相应的if
条件外,我无法找到一个好方法来执行此操作
{%if model_name.field_name%}
始终为ManytoManyField
s返回true
(因为它是ManyRelatedManager
)
{%if model_name.field_name | length>0%}
始终为ManytoManyField
返回false
{%if model_name.field_name.all%}
可能适用于ManyToManyFields
,但不适用于其他字段(如CharField
)
是否有一种方法可以检查字段中是否有可用值(是
ManytoManyField
还是简单的CharField
)?我可以使用multipleif-else
首先检查字段类型,然后运行相应的检查,但这样做感觉很不直观,因为这感觉像是证明模板标记正确性的常见用例。您可以使用get_fields
使其更干净:
在您的例子中,它看起来像这样(这是伪代码):
但我也同意@cezar的意见,即您应该将类似的内容移动到
视图中。py
如果您使用模板过滤器,它的外观将非常明显:
from django import template
register = template.Library()
@register.filter
def is_not_empty(field):
try:
return field.count()
except (AttributeError, TypeError):
return field
这就是我最后做的: @cezar的建议很有道理,因此我将逻辑移到了
views.py
(毕竟,是否显示值的逻辑将落在“显示内容”的范围内,因此转到视图,而不是如何在模板中显示)
此外,现在不再将模型对象返回到模板,而是返回一个只包含相关值的dict。许多字段(如果不为空)在目录中显示为列表
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的另外两个方法的调用,并将它们移动了
很高兴了解上述方法是否可以改进。如果您需要此类逻辑,也许最好将其放入您的
视图.py
。应该使用RelatedManager的某种方法调用ManyToManyField或ForeignKeyField中的关联对象:all
,或者filter
@cezar-谢谢,我将逻辑移到了views.py。发布我的最终代码作为答案。谢谢@Sardorbek-你的意思是在模板中使用get_fields()、getattr()、get_internal_type()等相应的逻辑吗?我已经发布了我的代码-现在将逻辑移到views.py,有趣的是,最终的代码看起来类似于模板的伪代码,因此upvoting@Anupam是的,它可以在模板中使用,但我强烈建议在views.py中这样做,正如您所做的那样。
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})