python - Subcontratación de multijugador de Django: reconstrucción de la fecha en la publicación mediante un multwidget personalizado
django-widget django-multiwidget (1)
Así que mi libro de django está de vuelta en la universidad y estoy luchando para solucionar este problema.
He subclasificado django.forms.widgets.MultiWidget
así:
class DateSelectorWidget(widgets.MultiWidget):
def __init__(self, attrs=None, dt=None, mode=0):
if dt is not None:
self.datepos = dt
else:
self.datepos = date.today()
# bits of python to create days, months, years
# example below, the rest snipped for neatness.
years = [(year, year) for year in year_digits]
_widgets = (
widgets.Select(attrs=attrs, choices=days),
widgets.Select(attrs=attrs, choices=months),
widgets.Select(attrs=attrs, choices=years),
)
super(DateSelectorWidget, self).__init__(_widgets, attrs)
def decompress(self, value):
if value:
return [value.day, value.month, value.year]
return [None, None, None]
def format_output(self, rendered_widgets):
return u''''.join(rendered_widgets)
Lo que me da un campo de selección de fecha ingenioso como tal:
Mi pregunta es muy simple en realidad. Cuando presento dicho formulario a su método de manejo (que utiliza un proceso como este:
forminstance = ModelNameForm(request.POST, instance=modelinstance)
if forminstance.is_valid():
forminstance.save()
Esto falla, porque Django no sabe cómo tomar mi multi-widget y convertirlo de nuevo al tipo de campo subyacente, que está establecido en models.py
a DateField()
, claramente.
Ahora, los comentarios sobre MultiWidget en la fuente de django me dan esta sugerencia útil:
Probablemente querrá usar esta clase con MultiValueField.
Pero la cosa es que probablemente no. Quiero mantener mi DateField()
porque es muy útil y no tiene sentido duplicarlo. Lo que tengo que hacer entonces es convertir estos múltiples campos de nuevo en una única fecha de datación válida ( yyyy-mm-dd
) para insertarlos en la base de datos.
Mi pregunta es entonces:
¿Cómo? ¿Cuál es la mejor manera de lograr esto?
Respondí mi propia pregunta!
Implementé este método:
def value_from_datadict(self, data, files, name):
datelist = [widget.value_from_datadict(data, files, name + ''_%s'' % i) /
for i, widget in enumerate(self.widgets)]
try:
D = date(day=int(datelist[0]), month=int(datelist[1]), /
year=int(datelist[2]))
return str(D)
except ValueError:
return ""
value_from_datadict
extrae los datos de todos los sub-widgets de todo el post datadict. Lo que he hecho es extraer las distintas contrapartes de fecha y usar el constructor de fecha para validar la fecha. Si es válido, imprimimos la cadena en el formato correcto; de lo contrario, devolvemos una cadena vacía que
forminstance.is_valid()
cogerá.
Me encanta cuando hago esto!