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 时不为空的字段。

除了使用许多ifelse 来检查字段类型然后运行相应的if 条件之外,我无法找到一个好的方法。

% if model_name.field_name % 总是为ManytoManyFields 返回true(因为它是ManyRelatedManager

% if model_name.field_name|length > 0 % 总是为ManytoManyFields 返回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 模板中是不是有小数位实数,如果为零,则四舍五入

检查元素是不是在模型中 - Django 模板

Django:检查模板中ManyToMany字段中的值

Django:检查模型字段是不是已回答

当我在 for 中有一个 if 时,Django 模板检查是不是为空

Django检查字段是不是为空?