Django - 通过验证过滤范围内的日期

时间:2016-04-21 11:48:57

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

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

Model.py

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

过滤器需要遵循以下条件:

  1. 过滤" session_start" " start_date"范围内的字段和" end_date"。
  2. 验证" start_date"和" end_date"领域。这意味着" start_date" value应该是" end_date"之前的日期。值。如果传递了无效数据,则根据默认值返回queryset。默认值为 -
  3. start_date =从今天起30天后。

    end_date =今天。

    我写了以下代码来过滤" session_start"在" start_date"之间的范围内的字段和" end_date"。现在我停留在检查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']
    

2 个答案:

答案 0 :(得分:3)

您实际上可以在django-filters过滤器中使用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

答案 1 :(得分:1)

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