I have some 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"))
I'm then using Django-rest-framework to create an API endpoint for this class, with django-filter providing a 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'm able to filter by event_type
and event_model
, but am having trouble filtering by the timestamp field. Essentially, I want to make an API call that equates to the following:
AuditEvent.objects.filter(timestamp__gte='2016-01-02 00:00+0000')
which I would expect I could do as follows:
response = self.client.get("/api/v1/events/?timestamp=2016-01-02 00:00+0000", **{'HTTP_ACCEPT': 'application/json'})
though that is incorect. How do I make an API call that returns all objects with a timestamp greater than or equal to a certain value?
The simplest way to filter the queryset of any view that subclasses GenericAPIView is to override the .get_queryset() method. Overriding this method allows you to customize the queryset returned by the view in a number of different ways.
To expand on Flaiming's answer, if you're only ever going to be filtering via ISO datetime formats, it helps to overwrite the defaults to always use the IsoDateTimeFilter
. This can be done per filterset with e.g.
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 then won't have to worry about setting a different filter for each lookup expression and each field.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With