Plantillas de Django: versión detallada de una elección

Tengo un modelo:

from django.db import models CHOICES = ( ('s', 'Glorious spam'), ('e', 'Fabulous eggs'), ) class MealOrder(models.Model): meal = models.CharField(max_length=8, choices=CHOICES) 

Tengo un formulario:

 from django.forms import ModelForm class MealOrderForm(ModelForm): class Meta: model = MealOrder 

Y quiero usar formtools.preview. La plantilla predeterminada imprime la versión corta de la elección (‘e’ en lugar de ‘Huevos fabulosos’), porque utiliza

 {% for field in form %}  {{ field.label }}: {{ field.data }}  {% endfor %}. 

Me gustaría una plantilla tan general como la mencionada, pero imprimiendo ‘Huevos fabulosos’ en su lugar.

[como tenía dudas de cuál es la verdadera pregunta, lo hice en forma rotunda para todos nosotros :)]

Sé cómo obtener la versión detallada de una elección de una manera que a su vez es fea:

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

El verdadero problema es que necesito obtener la opción seleccionada, y la única forma en que me viene a la mente iterar a través de las opciones y verificar {% ifequals currentChoice.0 choiceField.data %} , que es aún más feo.

¿Se puede hacer fácilmente? ¿O necesita alguna progtwigción de etiqueta de plantilla? ¿No debería estar ya disponible en django?

En las plantillas de Django puede usar el get_FOO_display()get_FOO_display() “, que devolverá el alias legible para el campo, donde ‘FOO’ es el nombre del campo.

Nota: en caso de que las plantillas estándar de FormPreview no lo estén usando, siempre puede proporcionar sus propias plantillas para ese formulario, que contendrá algo así como {{ form.get_meal_display }} .

La mejor solución para su problema es usar funciones auxiliares. Si las elecciones se almacenan en la variable CHOICES y el campo de modelo que almacena la opción seleccionada es ‘ elecciones ‘, entonces puede usar directamente

  {{ x.get_choices_display }} 

en tu plantilla Aquí, x es la instancia modelo. Espero eso ayude.

Mis disculpas si esta respuesta es redundante con cualquiera de las enumeradas anteriormente, pero parece que esta no se ha ofrecido aún, y parece bastante limpia. Así es como he resuelto esto:

 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] 

Mi vista pasa una Scoop a la plantilla (nota: no Scoop.values ​​()), y la plantilla contiene:

 {{ scoop.flavor_verbose }} 

Basándonos en la respuesta de Noah, aquí hay una versión inmune a los campos sin opciones:

 #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 

No estoy seguro de si está bien usar un filtro para tal fin. Si alguien tiene una solución mejor, estaré encantado de verla 🙂 ¡Gracias, Noah!

Podemos extender la solución de filtro de Noah para que sea más universal en el tratamiento de datos y tipos de campo:

  {% for item in query %}  {% for field in fields %}  {% endfor %}  {% endfor %} 
{{item|human_readable:field}}

Aquí está el código:

 #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) 

No creo que haya una forma integrada de hacerlo. Un filtro podría hacer el truco, sin embargo:

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

Entonces puedes hacer:

 {% for field in form %}  {{ field.label }}: {{ field.data|display }}  {% endfor %} 

Agregue a su models.py una función simple:

 def get_display(key, list): d = dict(list) if key in d: return d[key] return None 

Ahora puede obtener un valor detallado de los campos de opciones como ese:

 class MealOrder(models.Model): meal = models.CharField(max_length=8, choices=CHOICES) def meal_verbose(self): return get_display(self.meal, CHOICES) 

Upd .: No estoy seguro, es esa solución “pythonic” y “django-way” suficiente o no, pero funciona. 🙂