Django - How to filter by date with Django Rest Framework?

I have a model with a timestamp field:

models.py

class Event(models.Model): event_type = models.CharField( max_length=100, choices=EVENT_TYPE_CHOICES, verbose_name=_("Event Type") ) event_model = models.CharField( max_length=100, choices=EVENT_MODEL_CHOICES, verbose_name=_("Event Model") ) timestamp = models.DateTimeField(auto_now=True, verbose_name=_("Timestamp")) 

Then I use the Django-rest-framework to create an API endpoint for this class, with a django filter that provides filtering functionality as follows:

 from .models import Event from .serializers import EventSerializer from rest_framework import viewsets, filters from rest_framework import renderers from rest_framework_csv import renderers as csv_renderers class EventsView(viewsets.ReadOnlyModelViewSet): """ A read only view that returns all audit events in JSON or CSV. """ queryset = Event.objects.all() renderer_classes = (csv_renderers.CSVRenderer, renderers.JSONRenderer) serializer_class = EventSerializer filter_backends = (filters.DjangoFilterBackend,) filter_fields = ('event_type', 'event_model', 'timestamp') 

with the following settings:

 REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('rest_framework.filters.DjangoFilterBackend',), } 

I can filter event_type and event_model , but I have a problem with filtering by timestamp field. Essentially, I want to make an API call that matches the following:

 AuditEvent.objects.filter(timestamp__gte='2016-01-02 00:00+0000') 

which, I expect, could do as follows:

 response = self.client.get("/api/v1/events/?timestamp=2016-01-02 00:00+0000", **{'HTTP_ACCEPT': 'application/json'}) 

although it is. How to create an API call that returns all objects with a timestamp greater than or equal to a specific value?

+5
source share
3 answers

To expand the response to the Flaiming call, if you are only going to filter through ISO date and time formats, this helps to overwrite the default settings so that you always use IsoDateTimeFilter . This can be done for each set of filters, for example,

 from django.db import models as django_models import django_filters from rest_framework import filters from rest_framework import viewsets class EventFilter(filters.FilterSet): class Meta: model = Event fields = { 'timestamp': ('lte', 'gte') } filter_overrides = { django_models.DateTimeField: { 'filter_class': django_filters.IsoDateTimeFilter }, } class EventsView(viewsets.ReadOnlyModelViewSet): ... filter_class = EventFilter 

You do not have to worry about setting a different filter for each search expression and each field.

+5
source

You can create a specific FilterSet as follows:

 import django_filters from rest_framework import filters from rest_framework import viewsets class EventFilter(filters.FilterSet): timestamp_gte = django_filters.DateTimeFilter(name="timestamp", lookup_expr='gte') class Meta: model = Event fields = ['event_type', 'event_model', 'timestamp', 'timestamp_gte'] class EventsView(viewsets.ReadOnlyModelViewSet): ... filter_class = EventFilter 

How can you filter "/api/v1/events/?timestamp_gte=2016-01-02"

EDIT: To clarify, this example uses the django-filter library.

+2
source

IsoDateTimeFilter very picky about the input format; instead:

  • 2016-01-02 00: 00 + 0000

using:

  • 2016-01-02T00: 00: 00Z
+2
source

All Articles