【问题标题】:Django - Filter a date within a range with validationDjango - 通过验证过滤范围内的日期
【发布时间】:2016-08-14 14:25:27
【问题描述】:

我在模型中有一个名为“session_start”的 DateTimeField。我正在尝试过滤一个日期范围内的 session_start 字段。

Model.py

class TimeCard(models.Model):
    profile = models.ForeignKey(settings.AUTH_USER_MODEL)
    session_start = models.DateTimeField()

过滤器需要满足以下条件:

  1. 在“start_date”和“end_date”范围内过滤“session_start”字段。
  2. 验证“start_date”和“end_date”字段。这意味着“start_date”值应该是“end_date”值之前的日期。如果传递了无效数据,则根据默认值返回查询集。默认值为 -

start_date = 从今天开始的 30 天。

end_date = 今天。

我编写了以下代码来过滤“start_date”和“end_date”之间的范围内的“session_start”字段。现在我陷入了检查 start_date 大于 end_date 的条件。我该怎么做才能进行验证?

filter.py

class TimeCardFilter(filters.FilterSet):

    start_date = django_filters.DateTimeFilter(name="session_start", lookup_type='gte')
    end_date = django_filters.DateTimeFilter(name="session_start", lookup_type='lte')

    class Meta:
        model = TimeCard
        fields = ['profile', 'start_date', 'end_date']

【问题讨论】:

    标签: python django django-rest-framework django-filter


    【解决方案1】:

    您实际上可以在django-filters Filtersets 中使用django forms,因此您可以在表单的clean() 方法中管理验证。您的 filter.py 可能看起来像这样:

    import django_filters
    from app.models import TimeCard
    from django import forms
    
    
    class TimeCardFilter(django_filters.FilterSet):
    
        start_date = django_filters.DateTimeFilter(
            name="session_start",
            lookup_type="gte")
        end_date = django_filters.DateTimeFilter(
            name="session_start",
            lookup_type="lte")
    
        class Meta:
            model = TimeCard
            form = TimeCardForm
    
    
    class TimeCardForm(forms.Form):
    
        def clean(self):
            cleaned_data = super(TimeCardForm, self).clean()
            start_date = cleaned_data.get("start_date")
            end_date = cleaned_data.get("end_date")
    
            if start_date > end_date:
                self._errors['start_date'] = self._errors.get('start_date', [])
                self._errors['start_date'].append("Start date must be before end date.")
    
            return cleaned_data
    

    【讨论】:

      【解决方案2】:

      Based on the source code,您的选择可能有限。看起来您最好的选择是覆盖 qs 属性。

      class TimeCardFilter(filters.FilterSet):
      
          start_date = django_filters.DateTimeFilter(name="session_start", lookup_type='gte')
          end_date = django_filters.DateTimeFilter(name="session_start", lookup_type='lte')
      
          @property
          def qs(self):
              # Parent class defines a property _qs which represents the updated queryset
              if hasattr(self, '_qs'):
                 return self._qs
              # qs property is the place that FilterSet generates a query string.
              # it finds the values in the self.form.cleaned_data or self.form[name].value()
              orig_start = self.form.cleaned_data['session_start']
              orig_end = self.form.cleaned_data['session_end']
      
              # Your conditional logic would go here.
              if orig_start > orig_end:
                 # You'll need real values here, these clearly are fake.
                 self.form.cleaned_data['session_start'] = now()-30 * 24 * 3600
                 self.form.cleaned_data['session_end'] = now()
      
              # Be sure to return FilterSet's actual QS.
              return super(TimeCardFilter, self).qs()
      
          class Meta:
              model = TimeCard
              fields = ['profile', 'start_date', 'end_date']
      

      【讨论】:

        猜你喜欢
        • 2015-04-10
        • 2020-09-08
        • 1970-01-01
        • 1970-01-01
        • 2016-02-21
        • 2020-03-09
        • 2014-09-04
        • 2019-07-05
        • 1970-01-01
        相关资源
        最近更新 更多