python - Durationfield django
django-forms django-1.8 (2)
Dificultad para usar el nuevo campo de duración en Django 1.8
Estoy teniendo problemas con el nuevo DurationField de Django para modelos.
Quiero que el usuario pueda elegir si la duración de un evento en mi aplicación web es de 1 día, 3 días o 5 días, con la opción predeterminada de 3 días.
Al comienzo de mi modelo, declaro las opciones:
SHORT = datetime.timedelta(days=1)
MEDIUM = datetime.timedelta(days=3)
LONG = datetime.timedelta(days=5)
DURATION_CHOICES = ((SHORT, ''1 day''),(MEDIUM, ''3 days''), (LONG, ''5 days''),)
Luego, a continuación, declaro DurationField:
duration = models.DurationField(choices = DURATION_CHOICES, default = MEDIUM)
Creé un ModelForm para el modelo y lo presenté en la plantilla adecuada. En el formulario, "3 días" fue la opción preseleccionada en el menú desplegable, y "1 día" y "5 días" también son opciones. Sin embargo, cuando envío el formulario, obtengo el error de validación de formulario "Seleccione una opción válida. 3 días, 0:00:00 no es una de las opciones disponibles".
Sin embargo, cuando elimino las opciones de DurationField y dejo el valor predeterminado:
duration = models.DurationField(default = MEDIUM)
Puedo enviar sin ningún problema. ¿Qué estoy haciendo mal aquí?
De alguna manera choices
opción de choices
modelo no timedelta
cadena timedelta
cuando se timedelta
o convierte en template
.
Y el Field
DurationField
Field
DurationField
no funciona ...
Lo resolví usando ChoiceField
Código:
class TestForm(ModelForm):
SHORT_1 = str(timedelta(days=1)).replace(''day,'', '''')
SHORT = SHORT_1.replace('' '','' '')
MEDIUM_1 = str(timedelta(days=3)).replace(''days,'', '''')
MEDIUM = MEDIUM_1.replace('' '','' '')
LONG_1 = str(timedelta(days=-5)).replace(''days,'', '''')
LONG = LONG_1.replace('' '','' '')
DURATION_CHOICES = ((SHORT, ''1 day''),(MEDIUM, ''3 days''), (LONG, ''5 days''),)
duration = forms.ChoiceField(widget = forms.Select(),
choices = (DURATION_CHOICES), initial=''MEDIUM'', required = True,)
class Meta:
model = Test
fields = [''duration'']
No sé si no es recomendable o no ... Estoy buscando demasiado por qué django no funciona por defecto ...
Tuve el mismo problema. El problema se explica en este ticket de corrección de errores.
https://code.djangoproject.com/ticket/24897
La mejor forma de arreglar esto es utilizar este campo personalizado mientras espera que el equipo de django lo solucione:
"""
This is a temp DurationField with a bugfix
"""
standard_duration_re = re.compile(
r''^''
r''(?:(?P<days>-?/d+) (days, )?)?''
r''((?:(?P<hours>/d+):)(?=/d+:/d+))?''
r''(?:(?P<minutes>/d+):)?''
r''(?P<seconds>/d+)''
r''(?:/.(?P<microseconds>/d{1,6})/d{0,6})?''
r''$''
)
# Support the sections of ISO 8601 date representation that are accepted by
# timedelta
iso8601_duration_re = re.compile(
r''^P''
r''(?:(?P<days>/d+(./d+)?)D)?''
r''(?:T''
r''(?:(?P<hours>/d+(./d+)?)H)?''
r''(?:(?P<minutes>/d+(./d+)?)M)?''
r''(?:(?P<seconds>/d+(./d+)?)S)?''
r'')?''
r''$''
)
def parse_duration(value):
"""Parses a duration string and returns a datetime.timedelta.
The preferred format for durations in Django is ''%d %H:%M:%S.%f''.
Also supports ISO 8601 representation.
"""
match = standard_duration_re.match(value)
if not match:
match = iso8601_duration_re.match(value)
if match:
kw = match.groupdict()
if kw.get(''microseconds''):
kw[''microseconds''] = kw[''microseconds''].ljust(6, ''0'')
kw = {k: float(v) for k, v in six.iteritems(kw) if v is not None}
return datetime.timedelta(**kw)
class DurationField(CoreDurationField):
def to_python(self, value):
if value is None:
return value
if isinstance(value, datetime.timedelta):
return value
try:
parsed = parse_duration(value)
except ValueError:
pass
else:
if parsed is not None:
return parsed
raise exceptions.ValidationError(
self.error_messages[''invalid''],
code=''invalid'',
params={''value'': value},
)