【问题标题】:Durationfield djangoDurationfield Django
【发布时间】:2015-06-07 18:55:27
【问题描述】:

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

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

我希望用户能够选择我的 web 应用上的事件持续时间是 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)

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

【问题讨论】:

    标签: python django django-forms django-1.8


    【解决方案1】:

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

    还有Model @987654321@ Field @987654322@ 不工作...

    我用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 默认不工作......

    【讨论】:

      【解决方案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-22
      • 1970-01-01
      • 1970-01-01
      • 2023-02-15
      • 1970-01-01
      • 2016-01-11
      • 2022-11-17
      • 2021-01-02
      • 2019-07-30
      相关资源
      最近更新 更多