8

在 Django 1.8 中使用新的 DurationField 的困难

我在使用 Django 的新DurationField模型时遇到了一些麻烦。

我希望用户能够选择我的 webapp 上的事件持续时间是 1 天、3 天还是 5 天,默认选择是 3 天。

在我的模型开始时,我声明了选择:

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

然后在下面,我声明了 DurationField:

duration = models.DurationField(choices = DURATION_CHOICES, default = MEDIUM)

我为模型创建了一个 ModelForm,并在适当的模板上渲染它。在表单上,​​“3 天”是下拉菜单中的预选选项,“1 天”和“5 天”也是选项。但是,当我提交表单时,我收到表单验证错误“选择一个有效的选择。3 天,0:00:00 不是可用的选择之一。”

但是,当我从 DurationField 中删除选项并保留默认值时:

duration = models.DurationField(default = MEDIUM)

我可以毫无问题地提交。我在这里做错了什么?

4

2 回答 2

2

是否有同样的问题,此错误修复票中解释了问题

https://code.djangoproject.com/ticket/24897

解决此问题的最佳方法是在等待 django 团队解决此问题时使用此自定义字段:

    """
    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},
            )
于 2015-06-02T10:52:10.297 回答
0

不知何故模型choices选项未给出timedelta字符串时render或转换为template.

Model DurationField Field DurationField 不工作...

我通过使用解决了它ChoiceField

代码:

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']

我不知道它是否不推荐......我也在寻找为什么 django 默认不工作......

于 2015-04-08T08:38:45.297 回答