Django模板-检查字段中是否有值,如果有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

这看起来相当简单,但我无法从SO或Django文档(使用Django 1.10)中找到一个好的解决方案

我正在获取模板中的模型对象,并仅显示那些具有值(即不为空或null)或不为空(如果为ManyToManyField)的字段

除了使用许多
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
)?我可以使用multiple
if-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})