Шаблоны Django: подробная версия выбора

У меня есть модель:

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.

[as I had doubts where's the real question, I bolded it for all of us :)]

Я знаю, как получить подробную версию выбора таким образом, который сам по себе уродлив:

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

Настоящая боль в том, что мне нужно сделать выбранный выбор, и единственный способ, который приходит мне в голову, это перебирать выбор и проверять{% ifequals currentChoice.0 choiceField.data %}, что еще страшнее.

Это можно сделать легко? Или нужно какое-то программирование тегов-шаблонов? Разве это не доступно уже в django?

Ответы на вопрос(7)

вот версия, невосприимчивая к полям без выбора:

#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

Я не уверен, нормально ли использовать фильтр для этой цели. Если у кого-нибудь есть лучшее решение, я буду рад его видеть :) Спасибо, Ной!

 07 июл. 2014 г., 08:56
отличная идея с использованием hasattr на выбор!
 15 февр. 2011 г., 16:04
+1 за упоминание вашего пути # annoyances / templatetags / ... LOL ... Я использую get_FOO_display (), который упоминается в нижней части формы документов.

Лучшее решение вашей проблемы - использовать вспомогательные функции. Если варианты хранятся в переменнойCHOICES и поле модели, в котором хранится выбранный выбор, является & amp;choices& APOS; тогда вы можете напрямую использовать

 {{ x.get_choices_display }}

в вашем шаблоне. Здесь х - это экземпляр модели. Надеюсь, поможет.

 26 мая 2012 г., 15:42
Почему бы вы ответили так через 2 года после того, как полезный ответ уже существует? И кто бы это проголосовал? Это тот же ответ, что и @roberto всего 2 года спустя ....
 30 июл. 2013 г., 10:04
@ Mark0978 причина, по которой этот голос был отклонен, заключается в том, что (для меня) было более понятно, чем следовать «Топ проголосовавшим». ответ. YMMV.

если этот ответ избыточен для любого из перечисленных выше, но кажется, что этот еще не был предложен, и кажется довольно чистым. Вот как я решил эту проблему:

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 в шаблон (примечание:not Scoop.values ()), а шаблон содержит:

{{ scoop.flavor_verbose }}
 04 июл. 2017 г., 23:14
спасибо :) это было именно то, что я искал.

Я не думаю, что есть какой-либо встроенный способ сделать это. Фильтр мог бы добиться цели, хотя:

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

В шаблонах Django вы можете использовать & quot;get_FOO_display()& Quot; метод, который будет возвращать читаемый псевдоним для поля, где «FOO»; это имя поля.

Примечание: в случае стандартаFormPreview шаблоны не используют его, то вы всегда можетепредоставить свои собственные шаблоны для той формы, которая будет содержать что-то вроде{{ form.get_meal_display }}.

 27 февр. 2014 г., 18:13
Обратите внимание, что это использование не ограничено представлениями, get_FOO_display () - это метод самого объекта модели, поэтому вы можете использовать его и в коде модели! Например, в __unicode __ () это очень удобно
 23 сент. 2011 г., 11:55
Я всегда забываю этот
 Artur Gajowy10 июл. 2009 г., 00:40
Да, я знаю. Это не так широко (универсально), хотя - если вы не знаете способ итерации в шаблоне по всем методам get_FOO_display объекта модели :) Я немного ленив для написания неуниверсальных шаблонов;) Более того, документы скажем, это метод экземпляра модели. Следовательно, это должна быть модельная форма, привязанная к существующему объекту, что не соответствует действительности, а также не является общим.

Добавьте в файл 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)    

Upd .: Я не уверен, что это решение & # x201C; pythonic & # x201D; и & # x201C; django-way & # x201D; Достаточно или нет, но это работает. :)

Мы можем расширить решение фильтра путемНой  быть более универсальным в работе с типами данных и полей:

<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)
 03 окт. 2011 г., 10:18
@ArturGajowy Да, на сегодняшний день в Django нет такой функции по умолчанию. Я предложил это,who knows, maybe it will be approved.
 Artur Gajowy30 сент. 2011 г., 23:38
Кажется, довольно универсальный :) Не могу сказать наверняка, потому что я не делал слишком много Python или Django с того времени. Однако довольно грустно, что ему все еще нужен фильтр третьей стороны (не включенный в Django) (в противном случае вы бы сказали нам, Иван, не так ли?)) ...

Ваш ответ на вопрос