我有一个模特:
from django.db import models
CHOICES = (
('s', 'Glorious spam'),
('e', 'Fabulous eggs'),
)
class MealOrder(models.Model):
meal = models.CharField(max_length=8, choices=CHOICES)
我有一张表格:
from django.forms import ModelForm
class MealOrderForm(ModelForm):
class Meta:
model = MealOrder
我想使用formtools.preview。默认模板打印选择的短版本('e'而不是'Fabulous eggs'),因为它使用
{% for field in form %}
<tr>
<th>{{ field.label }}:</th>
<td>{{ field.data }}</td>
</tr>
{% endfor %}.
我想要一个像上面提到的一般模板,而是打印'Fabulous eggs'。
[因为我怀疑真正的问题在哪里,我为我们所有人加油:)]
我知道如何以一种本身丑陋的方式获得一个选择的冗长版本:
{{ form.meal.field.choices.1.1 }}
真正的痛苦是我需要做出选择的选择,而我想到的唯一方法是迭代选择并检查{% ifequals currentChoice.0 choiceField.data %}
,这甚至更加丑陋。
可以轻松完成吗?或者它需要一些模板标签编程?难道不应该在django中提供吗?
答案 0 :(得分:231)
在Django模板中,您可以使用“get_FOO_display()
”方法,该方法将返回字段的可读别名,其中“FOO”是字段的名称。
注意:如果标准FormPreview
模板未使用该模板,则您始终可以provide your own templates获取该表单,其中包含{{ form.get_meal_display }}
之类的内容。
答案 1 :(得分:42)
解决问题的最佳方法是使用辅助函数。 如果选项存储在变量 CHOICES 中,并且存储所选选项的模型字段为“选项”,则可以直接使用
{{ x.get_choices_display }}
在你的模板中。这里,x是模型实例。 希望它有所帮助。
答案 2 :(得分:36)
如果上面列出的任何答案都是多余的,我很抱歉,但似乎尚未提供此答案,而且看起来相当干净。以下是我解决这个问题的方法:
from django.db import models
class Scoop(models.Model):
FLAVOR_CHOICES = [
('c', 'Chocolate'),
('v', 'Vanilla'),
]
flavor = models.CharField(choices=FLAVOR_CHOICES)
def flavor_verbose(self):
return dict(Scoop.FLAVOR_CHOCIES)[self.flavor]
我的视图将Scoop传递给模板(注意:不 Scoop.values()),模板包含:
{{ scoop.flavor_verbose }}
答案 3 :(得分:9)
根据诺亚的回复,这里的版本不受没有选择的字段的影响:
#annoyances/templatetags/data_verbose.py
from django import template
register = template.Library()
@register.filter
def data_verbose(boundField):
"""
Returns field's data or it's verbose version
for a field with choices defined.
Usage::
{% load data_verbose %}
{{form.some_field|data_verbose}}
"""
data = boundField.data
field = boundField.field
return hasattr(field, 'choices') and dict(field.choices).get(data,'') or data
我不确定是否可以使用过滤器来实现此目的。如果有人有更好的解决方案,我会很高兴看到它:)谢谢诺亚!
答案 4 :(得分:6)
我们可以通过Noah扩展过滤器解决方案,以便在处理数据和字段类型时更加通用:
<table>
{% for item in query %}
<tr>
{% for field in fields %}
<td>{{item|human_readable:field}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
以下是代码:
#app_name/templatetags/custom_tags.py
def human_readable(value, arg):
if hasattr(value, 'get_' + str(arg) + '_display'):
return getattr(value, 'get_%s_display' % arg)()
elif hasattr(value, str(arg)):
if callable(getattr(value, str(arg))):
return getattr(value, arg)()
else:
return getattr(value, arg)
else:
try:
return value[arg]
except KeyError:
return settings.TEMPLATE_STRING_IF_INVALID
register.filter('human_readable', human_readable)
答案 5 :(得分:5)
我认为没有任何内置方法可以做到这一点。但是过滤器可能会起到作用:
@register.filter(name='display')
def display_value(bf):
"""Returns the display value of a BoundField"""
return dict(bf.field.choices).get(bf.data, '')
然后你可以这样做:
{% for field in form %}
<tr>
<th>{{ field.label }}:</th>
<td>{{ field.data|display }}</td>
</tr>
{% endfor %}
答案 6 :(得分:3)
添加到models.py中的一个简单函数:
def get_display(key, list):
d = dict(list)
if key in d:
return d[key]
return None
现在,您可以获得类似的选择字段的详细值:
class MealOrder(models.Model):
meal = models.CharField(max_length=8, choices=CHOICES)
def meal_verbose(self):
return get_display(self.meal, CHOICES)
更新:我不确定,解决方案“pythonic”和“django-way”是否足够,但它确实有效。 :)
答案 7 :(得分:1)
您有Model.get_FOO_display(),其中FOO是具有选择项的字段的名称。
在您的模板中执行此操作:
{{ scoop.get_flavor_display }}