Django - 模板显示模型verbose_names和对象

8

我需要在模板中显示多个模型名称和对象。

这是我的视图

def contents(request):
  """Lists contents"""
  objects = [
    Model1.objects.all(),
    Model2.objects.all(),
    Model3.objects.all(),
    Model4.objects.all(),
  ]
  return render_to_response('content/contents.html', objs
  , context_instance=RequestContext(request)
  )

我有一个模板

{% for objs in objects %}
  <div class="content">
    <div class="title">{{ objs._meta.verbose_name }}</div>
    <ul>
    {% for obj in objs %}
      <li>{{ obj }}</li>
    {% endfor %}
    </ul>
  </div>
{% endfor %}

当然,objs._meta.verbose_name 是无法使用的。
有没有一种方法可以访问这个 verbose name 而不必为每个模型创建一个函数或为每个模型从视图分配该值?
4个回答

16

在模板中访问它时,您可能已经注意到Django不允许您使用下划线前缀从模板访问属性。因此,在不必为每个模型创建模型方法的情况下,访问任何给定对象的易读名称最简单的方法是创建一个模板标签:

@register.simple_tag 
def get_verbose_name(object): 
    return object._meta.verbose_name

不相关,但是你的模板中有一个错误,即你尝试在查询集而不是对象上访问_meta属性。因此,你的标题行应该像这样:

{% with objs|first as obj %}
    <div class="title">{% get_verbose_name obj %}</div>
{% endwith %}

工作正常。我最终使用了 {% get_verbose_name objs.0 %}(如果没有值,不确定它是否有效)。 - Pierre de LESPINAY
9
也许使用过滤器更加清晰。这几乎是相同的实现,但调用方法看起来更好。就像 {{ obj|verbose_name }} 或者 {{ obj.0|verbose_name }} 这样。 - Armando Pérez Marqués
+1 @Mandx,我认为你说的看起来更干净。做得好。 - Spike
问题在于如果没有objs,则objs.0可能未定义 :( - Pierre de LESPINAY
1
我认为最好从标签中使用 return queryset.model._meta.verbose_name,queryset 是整个结果集(而不是第一行)。 - Pierre de LESPINAY
2
我遇到了'str' object has no attribute '_meta'错误。Django版本是1.7。 - Mikhail Batcer

4

标签:

@register.simple_tag
def get_verbose_name(object, fieldnm): 
  return object._meta.get_field(fieldnm).verbose_name

HTML(year是我的模型中的字段名称)

<td><label class="control-label text-lg text-info"> {% get_verbose_name object 'year' %} </label></td>

感谢上面提供的参考。想分享一下我在寻找解决方案时发现的内容,以便其他人也能找到适合自己情况的解决方案。


2
在Django 3.x中,我发现这是最简单的方法。我通常将所有对象工具放在一个模块中:
from django import template

register = template.Library()

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

然后在模板中:
{{ object_name|verbose_name }}

1

另一种解决方案是对您的模型的QuerySet进行子类化:

class SomeQuerySet(models.QuerySet):
    @property
    def verbose_name(self):
        return self.model._meta.verbose_name

class SomeModel(models.Model):
    ...

    objects = SomeQuerySet.as_manager()

    class Meta:
        verbose_name = 'Some Model'

现在你可以直接从查询集中获取verbose_name,而无需遍历它:
<h1>{{ objects.verbose_name }}</h1>
{% for objs in objects %}
...

如果您想直接从模型实例中访问verbose_name,而不是从QuerySet中访问,您还需要在模型中定义一个属性:
class SomeModel(models.Model):
    ...

    objects = SomeQuerySet.as_manager()

    class Meta:
        verbose_name = 'Some Model'

    @property
    def verbose_name(self):
        return self._meta.verbose_name

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接