Django模板:选择的详细版本

Art*_*owy 122 django django-templates django-forms

我有一个模特:

from django.db import models

CHOICES = (
    ('s', 'Glorious spam'),
    ('e', 'Fabulous eggs'),
)

class MealOrder(models.Model):
    meal = models.CharField(max_length=8, choices=CHOICES)
Run Code Online (Sandbox Code Playgroud)

我有一个表格:

from django.forms import ModelForm

class MealOrderForm(ModelForm):
    class Meta:
        model = MealOrder
Run Code Online (Sandbox Code Playgroud)

我想使用formtools.preview.默认模板打印选择的短版本('e'而不是'Fabulous eggs'),因为它使用

{% for field in form %}
<tr>
<th>{{ field.label }}:</th>
<td>{{ field.data }}</td>
</tr>
{% endfor %}.
Run Code Online (Sandbox Code Playgroud)

我想要一个像上面提到的一般模板,但是打印'Fabulous eggs'代替.

[因为我怀疑真正的问题在哪里,我为所有人加粗了:)]

我知道如何以一种本身丑陋的方式获得一个选择的冗长版本:

{{ form.meal.field.choices.1.1 }}
Run Code Online (Sandbox Code Playgroud)

真正的痛苦是我需要得到所选择的选择,而我想到的唯一方法是迭代选择和检查{% ifequals currentChoice.0 choiceField.data %},这甚至更加丑陋.

可以轻松完成吗?或者它需要一些模板标签编程?难道这不应该在django中可用吗?

rob*_*rob 242

在Django模板中,您可以使用" get_FOO_display()"方法,该方法将返回字段的可读别名,其中"FOO"是字段的名称.

注意:如果标准FormPreview模板没有使用它,那么您始终可以为该表单提供自己的模板,其中包含类似的模板{{ form.get_meal_display }}.

  • 请注意,此用法不仅限于视图,get_FOO_display()是模型对象本身的方法,因此您也可以在模型代码中使用它!例如,在__unicode __()中它非常方便 (2认同)

Ree*_*ema 46

解决问题的最佳方法是使用辅助函数.如果选项存储在变量CHOICES中,并且存储所选选项的模型字段为" 选项 ",则可以直接使用

 {{ x.get_choices_display }}
Run Code Online (Sandbox Code Playgroud)

在你的模板中.这里,x是模型实例.希望能帮助到你.

  • @ Mark0978赞成这个答案的原因是因为(对我而言)更加清楚地遵循"最高投票"的答案.因人而异. (15认同)
  • 在有用的答案已经到位2年后,你为什么这样回答?谁会投票呢?与2年后的@roberto一样的答案.... (3认同)

小智 44

如果这个答案对于上面列出的任何答案都是多余的,我很抱歉,但似乎还没有提供这个答案,而且看起来相当干净.这是我如何解决这个问题:

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]
Run Code Online (Sandbox Code Playgroud)

我的视图将Scoop传递给模板(注意:不是 Scoop.values()),模板包含:

{{ scoop.flavor_verbose }}
Run Code Online (Sandbox Code Playgroud)


Art*_*owy 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
Run Code Online (Sandbox Code Playgroud)

我不确定是否可以使用过滤器来达到这个目的.如果有人有更好的解决方案,我会很高兴看到它:)谢谢你诺亚!


Iva*_*mov 6

我们可以扩展Noah的过滤器解决方案, 以便在处理数据和字段类型时更加通用:

<table>
{% for item in query %}
    <tr>
        {% for field in fields %}
            <td>{{item|human_readable:field}}</td>
        {% endfor %}
    </tr>
{% endfor %}
</table>
Run Code Online (Sandbox Code Playgroud)

这是代码:

#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)
Run Code Online (Sandbox Code Playgroud)


Noa*_*ing 5

我认为没有任何内置的方法可以做到这一点.但是过滤器可能会起到作用:

@register.filter(name='display')
def display_value(bf):
    """Returns the display value of a BoundField"""
    return dict(bf.field.choices).get(bf.data, '')
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

{% for field in form %}
    <tr>
        <th>{{ field.label }}:</th>
        <td>{{ field.data|display }}</td>
    </tr>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)