我正在尝试创建一个基本模板来显示所选实例的字段值及其名称 . 可以将其视为表格格式中该实例值的标准输出,其中第一列中的字段名称(如果在字段中指定,则特别是verbose_name)和第二列中该字段的值 .
例如,假设我们有以下模型定义:
class Client(Model):
name = CharField(max_length=150)
email = EmailField(max_length=100, verbose_name="E-mail")
我希望它在模板中输出如此(假设具有给定值的实例):
Field Name Field Value
---------- -----------
Name Wayne Koorts
E-mail waynes@email.com
我想要实现的是能够将模型的实例传递给模板,并能够在模板中动态迭代它,如下所示:
<table>
{% for field in fields %}
<tr>
<td>{{ field.name }}</td>
<td>{{ field.value }}</td>
</tr>
{% endfor %}
</table>
是否有一个整洁,“Django批准”的方式来做到这一点?这似乎是一项非常常见的任务,我需要经常为这个特定项目做这件事 .
20 回答
是的's not pretty, you' ll必须制作你自己的包装 . 看看builtin databrowse app,它具有你真正需要的所有功能 .
这可能被认为是一个黑客,但我在使用modelform_factory将模型实例转换为表单之前已经这样做了 .
Form类里面有很多更容易迭代的信息,它会以更多的开销为代价来实现相同的目的 . 如果您的设定尺寸相对较小,我认为性能影响可以忽略不计 .
当然,除了方便之外,还有一个优点是您可以在以后轻松将表格转换为可编辑的数据网格 .
我使用了https://stackoverflow.com/a/3431104/2022534但用这个替换了Django的model_to_dict()以便能够处理ForeignKey:
请注意,通过删除我不需要的原件部分,我已经简化了一点 . 你可能想把它们放回去 .
我建议写 one template tag 而不是编辑每个模型,这将返回 any model 给出的所有字段 .
每个对象都有字段列表
._meta.fields
.每个字段对象都有属性
name
,它将返回它的名称,并且随模型object
提供的方法value_to_string()
将返回其值 .剩下的就像在Django documentation中说的一样简单 .
以下是此模板标签的示例:
只是编辑@wonder
让Django处理除相关字段之外的所有其他字段 . 我觉得更稳定
Django 1.7解决方案对我来说:
变量与问题完全相同,但你绝对应该能够剖析这个例子
这里的关键是几乎使用模型的
.__dict__
views.py :
template :
在模板中,我使用过滤器来访问dict中的字段
filters.py :
看看django-etc应用程序 . 它有
model_field_verbose_name
模板标记,用于从模板中获取字段详细名称:http://django-etc.rtfd.org/en/latest/models.html#model-field-template-tagsmodel._meta.get_all_field_names()
将为您提供所有模型的字段名称,然后您可以使用model._meta.get_field()
以详细的名称工作,并使用getattr(model_instance, 'field_name')
从模型中获取值 .注意:在django 1.9中不推荐使用
model._meta.get_all_field_names()
. 而是使用model._meta.get_fields()
获取模型的字段,使用field.name
获取每个字段名称 .这是使用模型方法的另一种方法 . 此版本可解析选项列表/选项字段,跳过空白字段,并允许您排除特定字段 .
然后在你的模板中:
您可以使用Django的 to-python queryset序列化程序 .
只需在您的视图中输入以下代码:
然后在模板中:
它的巨大优势在于它处理关系字段 .
对于字段子集,请尝试:
终于在the dev mailing list找到了一个很好的解决方案:
在视图中添加:
在模板中添加:
您可以让表单为您完成工作 .
然后在模板中:
以下是我的,灵感来自shacker的
get_all_fields
. 它获取一个模型实例的字典,如果遇到关系字段,则递归地将字段值设为字典 .此函数主要用于将模型实例转储到json数据:
好吧,我知道这有点晚了,但是因为我在找到正确的答案之前偶然发现了这个,所以可能是其他人 .
来自django docs:
您可以使用
queryset
的values()
方法,它返回一个字典 . 此外,此方法接受要子集的字段列表 .values()
方法不适用于get()
,因此必须使用filter()
(参见QuerySet API) .在
view
...在
detail.html
...对于过滤器返回的 collection of instances :
详细地说......
我想出了以下方法,这对我有用,因为在每种情况下,模型都会有一个与之关联的ModelForm .
以下是我用于此特定视图的模板的摘录:
这件好事方法是我可以逐个模板地选择我想要显示字段标签的顺序,使用传入GetModelData的元组并指定字段名称 . 这也允许我排除某些字段(例如用户外键),因为只有通过元组传入的字段名称被内置到最终字典中 .
我不会接受这个作为答案,因为我相信有人可以拿出更多“Djangonic”的东西:-)
Update: 我选择这个作为最后的答案,因为这是我所需要的最简单的 . 感谢所有贡献答案的人 .
这种方法显示了如何使用类似django的ModelForm和类似{}的模板标记,但是所有表看起来都像数据输出,而不是表单 .
第一步是继承django的TextInput小部件:
然后我将django的ModelForm子类化为替换只读版本的默认小部件:
这些是我需要的唯一小部件 . 但是将这个想法扩展到其他小部件应该不难 .
根据Django 1.8的发布(以及Model _meta API的正式化,我想我会用更新的答案来更新它 .
假设相同的型号:
Django <= 1.7
Django 1.8(形式化模型_meta API)
在下面的例子中,我们将通过
Client._meta.get_fields()
利用retrieving all field instances of a model的形式化方法:实际上,我已经注意到上面的内容略微超出需要的范围(我同意!) . 简单比复杂更好 . 我将离开以上内容以供参考 . 但是,要在模板中显示,最好的方法是使用ModelForm并传入实例 . 您可以遍历表单(相当于迭代每个表单的字段)并使用label属性检索模型字段的verbose_name,并使用value方法检索值:
现在,我们渲染模板中的字段:
我正在使用这个,https://github.com/miracle2k/django-tables .
应该有一种内置的方法来做到这一点 . 我写了这个实用程序
build_pretty_data_view
,它接受一个模型对象和表单实例(一个基于你的模型的表单)并返回一个SortedDict
.此解决方案的好处包括:
它使用Django的内置
SortedDict
保留顺序 .尝试获取标签/ verbose_name时,如果未定义,则返回到字段名称 .
它还可以选择使用
exclude()
字段名称列表来排除某些字段 .如果您的表单类包含
Meta: exclude()
,但仍想返回值,则将这些字段添加到可选的append()
列表中 .要使用此解决方案,首先在某处添加此文件/函数,然后将其导入
views.py
.utils.py
所以现在你的
views.py
你可能会做这样的事情现在在您的
my-template.html
模板中,您可以迭代数据,如此...祝好运 . 希望这有助于某人!