【问题标题】:Django templates: loop through and print all available properties of an object?Django模板:循环并打印对象的所有可用属性?
【发布时间】:2011-01-14 02:52:26
【问题描述】:

我有一个名为manor_stats 的数据库对象,有大约30 个字段。对于大多数行,这些字段中的大多数将为空。

在我的模板中,我想遍历行中的所有字段,并仅打印非空字段的信息。

例如,有一个名为“name”的字段:我只想在模板中为那些字段不为空的对象打印<li>Name: {{ manor_stats.name }}</li>。理想情况下,我也想自动从某处提取“名称:”,而不是指定它。

我知道我可以使用{% if manor_stats.name %} 来检查每个字段是否为空,但我不想对所有字段都这样做 30 次。

这是我在 views.py 中的内容:

manor_stats = Manors.objects.get(idx=id)
return render_to_response('place.html', { 'place' : place, 'manor_stats' : manor_stats }, context_instance = RequestContext(request))

然后在 place.html 中,我想要一些大致像这样工作的东西(伪代码,??? 表示我不知道该怎么做的位):

{% if manor_stats %} 
<ul>
 {% for manor_stats.property??? in manor_stats %} 
  {% if manor_stats.property %} 
   <li>{{ manor_stats.property.field_name??? }} {{ manor_stats.property.value??? }}</li>
  {% endif %}
 {% endfor %
{% endif %}

希望这是有道理的......

【问题讨论】:

标签: django django-templates


【解决方案1】:

您可以向 Manors 模型添加一个方法,该方法将返回所有字段值,然后您可以在模板中循环遍历这些值,检查该值是否不为空。

--models.py

class Manors(models.Model)
  #field declarations

  def get_fields(self):
    return [(field.name, field.value_to_string(self)) for field in Manors._meta.fields]

-- manor_detail.html

{% for name, value in manor_stats.get_fields %}
  {% if value %}
    {{ name }} => {{ value }}
  {% endif %}
{% endfor %}

【讨论】:

  • 完美运行——正是我想要的。谢谢!
  • 你知道我怎样才能以某种方式在值旁边返回 field.verbose_name 吗?我想这只是正确的 Django 语法的问题,但我很困惑:(
  • 我对原来的答案做了一些更改。附加到字段的名称属性应该给你你想要的。
  • 再次感谢您!只做需要的事情。
  • 非常优雅。如果您想要更多的控制(例如解析选项列表/选择字段或排除某些字段的能力,请参阅这个更详细的模型方法版本,它获取所有字段并将它们返回到模板:stackoverflow.com/questions/2170228/…跨度>
【解决方案2】:

以下方法只需要定义一个自定义模板过滤器 (see the docs) - 它比必须将方法写入或复制到您需要此功能的每个模型中更干。

-- my_app/templatetags/my_tags.py

from django import template

register = template.Library()

@register.filter
def get_fields(obj):
    return [(field.name, field.value_to_string(obj)) for field in obj._meta.fields]

您需要重新启动服务器才能在模板中注册并使用新标签。

-- my_app/templates/my_app/my_template.html

{% load my_tags %}
<ul>
{% for key, val in object|get_fields %}
  <li>{{ key }}: {{ val }}</li>
{% endfor %}
</ul>

在 Django 1.11 中测试。

注意:由于 ._meta 是一个私有属性,它的功能在未来可能会发生变化。

感谢这篇文章中的其他答案让我走了大部分路,尤其是 W. Perrin。

【讨论】:

  • 我使用return [(field.name, field.verbose_name, field.value_to_string(obj)) for field in obj._meta.fields] 在模板中显示verbose_name 而不是name
【解决方案3】:

在 python 代码中使用 Model._meta.get_fields()。

>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
(<ManyToOneRel: admin.logentry>,
 <django.db.models.fields.AutoField: id>,
 <django.db.models.fields.CharField: password>,
 <django.db.models.fields.DateTimeField: last_login>,
 <django.db.models.fields.BooleanField: is_superuser>,
....

在模板中,我们可以定义一个过滤器来检索所有的字段。

├─my_app
│  │
│  ├─templatetags
│  │  │  my_filters.py
│  │

from django import template
register = template.Library()

@register.filter
def get_fields(obj):
    return obj._meta.get_fields()

{% for k,v in obj|get_fields %}
    <td> {{k}} </td>
{% endfor %}

查看此链接:https://docs.djangoproject.com/en/2.0/ref/models/meta/#retrieving-all-field-instances-of-a-model

【讨论】:

    猜你喜欢
    • 2021-10-09
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    • 2011-03-03
    • 2019-08-13
    相关资源
    最近更新 更多