在模板中迭代模型实例的字段名称和值。
在模板中迭代模型实例的字段名称和值。
我正在尝试创建一个基本模板,用于显示所选实例的字段值及其名称。可以将其视为以表格形式输出该实例的值的标准输出,其中字段名称(如果在字段上指定了verbose_name,则为该名称)位于第一列,该字段的值位于第二列。\n例如,假设我们有以下模型定义:\n
class Client(Model): name = CharField(max_length=150) email = EmailField(max_length=100, verbose_name="E-mail")
\n我希望在模板中以以下方式输出(假设存在具有给定值的实例):\n
字段名称 字段值 ---------- ----------- Name Wayne Koorts E-mail waynes@email.com
\n我想要实现的目标是能够将模型的实例传递给模板,并能够在模板中动态迭代它,类似于这样:\n
{{ field.name }} | {{ field.value }} |
\n是否有一种简洁、\"Django认可\"的方法来实现这一点?这似乎是一项非常常见的任务,而且我在这个特定项目中经常需要这样做。
问题的原因是在模板中迭代模型实例字段的名称和值时,可能会遇到一些困难。解决方法是通过在视图中使用model_to_dict函数将模型实例转换为字典,并将其传递给模板,在模板中使用for循环迭代字典的字段。
在这个例子中,作者在Django的开发者邮件列表上找到了一个解决方案。在视图中,作者导入了model_to_dict函数,并在show函数中使用该函数将模型实例转换为字典。然后,将转换后的字典传递给模板,并在模板中使用for循环迭代字典的字段。这样,模板就可以访问每个字段的名称和值,并进行相应的显示。
然而,这个解决方案并不适合所有情况,因为对于ForeignKey字段,model_to_dict函数返回的是unicode结果,而不是转换为字典。因此,在处理复杂对象时,不能轻松地将其序列化为字典。另外,作者指出在覆盖对象时可能存在风险,建议使用其他变量名。
另外,有人提出了另一种解决方案,即在视图中直接使用FooForm(instance=Foo.objects.get(pk=object_id))来实例化表单,这样可以更简单地处理可编辑字段。
最后,有人提出了一个问题,即如何只显示可编辑字段。但是,对于这个问题,目前还没有给出明确的解决方案。
问题的出现原因是用户想要在Django模板中迭代模型实例的字段名和值。用户想要解决的问题是如何限制结果只返回特定的字段。下面是解决方法:
用户可以使用Django的to-python查询集序列化器。在视图中加入以下代码:
from django.core import serializers data = serializers.serialize("python", SomeModel.objects.all())
然后在模板中加入以下代码:
{% for instance in data %} {% for field, value in instance.fields.items %} {{ field }}: {{ value }} {% endfor %} {% endfor %}
这种方法的优势在于它处理关联字段。如果只想返回字段的子集,可以尝试以下代码:
data = serializers.serialize('python', SomeModel.objects.all(), fields=('name','size'))
另一种解决方法是使用查询集的values()方法,它返回一个字典。此方法还可以接受一个字段列表来进行子集操作。详细信息可以查看官方文档的链接。具体实现代码如下:
data = SomeModel.objects.all().values('field1', 'field2')
希望这个方法是否允许传递字段的verbose_name没有得到明确的答案。
问题的原因是在Django 1.9之前,无法直接在模板中迭代模型实例的字段名称和值。解决方法是使用不同的方法来获取字段名称和值。
在Django 1.9及以后的版本中,可以使用model._meta.get_fields()
来获取模型的字段,使用field.name
来获取每个字段的名称。
在Django 1.9之前的版本中,可以使用model._meta.get_all_field_names()
获取模型的所有字段名称,然后使用model._meta.get_field()
来获取字段的详细名称,使用getattr(model_instance, 'field_name')
来获取模型中字段的值。
然而,这种方法仍然很繁琐,需要在视图中构建一种元对象,并将其传递到模板中,这比我想要的更像是一种hack方法。肯定有一种更简洁的方法吧?
可以像ModelForm一样将所有这些封装在一个类中。
我不认为你可以在模板中调用任何_开头的方法。
这个方法是可行的,但是你不应该依赖私有API(因为它以“_”为前缀)来实现它。依赖私有方法的问题在于,私有方法不能保证在不同版本中都能正常工作。
在Django 1.8 RC中,我得到了get_all_field_names()的弃用警告。有什么替代方法吗?
看起来Django正在试图使_meta更正式/官方化。链接
将其更改为被接受的答案,因为它远远获得了最多的赞同票,我认为这是大家认为最有用的答案。
刚刚建议编辑将model
更改为Model
,这样读者不会认为get_fields()返回的是实例的实际字段(及其值)
我认为不应该首选这种方法,因为我们不应该从模板中访问以下划线开头的属性。
Abrams,我该如何在Django 3中访问字段的值?