python django django-forms django-1.8

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}, )