首页 文章

Django模板:选择的详细版本

提问于
浏览
105

我有一个模特:

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 %}.

I'd like a template as general as the mentioned, but printing 'Fabulous eggs' instead.

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

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

{{ form.meal.field.choices.1.1 }}

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

可以轻松完成吗?还是需要一些模板标签编程?不应该在django中可用吗?

7 回答

  • 6

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

    注意:如果标准 FormPreview 模板没有使用它,那么你总是可以provide your own templates表示该表单,它将包含类似 {{ form.get_meal_display }} 的内容 .

  • 5

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

    {{ x.get_choices_display }}
    

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

  • 222

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

    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 }}
    
  • 34

    基于诺亚的回复,这里有一个版本免于没有选择的字段:

    #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
    

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

  • 9

    我们可以通过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)
    
  • 3

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

    @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 %}
    
  • 40

    添加到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”是否足够,但它确实有效 . :)

相关问题