bootstrap - linebreaksbr django
Plantillas de Django: versión detallada de una elección (7)
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 %}
<tr>
<th>{{ field.label }}:</th>
<td>{{ field.data }}</td>
</tr>
{% 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 programación de etiqueta de plantilla? ¿No debería estar ya disponible en django?
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. :)
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!
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 }}
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 %}
<tr>
<th>{{ field.label }}:</th>
<td>{{ field.data|display }}</td>
</tr>
{% endfor %}
Podemos extender la solución de filtro de Noah para que sea más universal en el tratamiento de datos y tipos de campo:
<table>
{% for item in query %}
<tr>
{% for field in fields %}
<td>{{item|human_readable:field}}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
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)