Neil
Neil

Reputation: 7202

Filtering list results by date (or other model params)

I have a model:

class Call(models.Model):
    created_on = models.DateTimeField(auto_now_add=True)
    send_on = models.DateTimeField(default=datetime.now)
    ...
    survey = models.ForeignKey(Survey, null=True, blank=True)

And a corresponding ModelSerializer:

class CallSerializer(serializers.HyperlinkedModelSerializer):
    url = serializers.HyperlinkedIdentityField(
        view_name='call-detail',
    )
    recipient = PhoneNumberField(read_only=False)
    status = SurveySerializer(source='survey', read_only=True)

    class Meta:
        model = Call
        fields = ('url', 'id', 'send_on', ...)
        lookup_field= 'pk'

And view:

class CallList(generics.ListCreateAPIView):
    serializer_class = CallSerializer
    permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrSuperuser,)

    def pre_save(self, obj):
        ...

    def get_queryset(self):
        """
        This view should return a list of all the calls
        for the currently authenticated user.
        """
        ...

I want to be able to support API list requests that let the caller get Calls filtered by date ranges for send_on. I am not sure how to do this in a RESTful way and what way it is meant to be done by DRF, but something like this:

mydomain.com/call/?start=2013-11-25T12:50:17&end=2013-11-28T12:50:17

And the return would list all calls with send_on between the given dates. What's the correct way to implement this with DRF?

Upvotes: 0

Views: 766

Answers (1)

mariodev
mariodev

Reputation: 15604

I think it's clearly explained in the DRF docs here.

So in your case it would look like:

from dateutil.parser import parse

class CallList(generics.ListCreateAPIView):
    # ...

    def get_queryset(self):
        filter = {}
        queryset = Call.objects.all()

        start_date = self.request.QUERY_PARAMS.get('start_date', None)
        end_date = self.request.QUERY_PARAMS.get('end_date', None)

        if start_date is not None:
            filter['send_on__gte'] = parse(start_date)

        if end_date is not None:
            filter['send_on__lte'] = parse(end_date)

        queryset = queryset.filter(**filter)

        return queryset

I use python-dateutil to easily parse the iso formatted datetime.

Upvotes: 6

Related Questions