Home:ALL Converter>Django - How to filter by date with Django Rest Framework?

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

Ask Time:2016-05-12T18:17:03         Author:orange1

Json Formatter

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?

Author:orange1,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/37183943/django-how-to-filter-by-date-with-django-rest-framework
clwainwright :

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.\nimport django_filters\nfrom django.db import models as django_models\nfrom django_filters import rest_framework as filters\nfrom rest_framework import viewsets\n\nclass EventFilter(filters.FilterSet):\n class Meta:\n model = Event\n fields = {\n 'timestamp': ('lte', 'gte')\n }\n\n filter_overrides = {\n django_models.DateTimeField: {\n 'filter_class': django_filters.IsoDateTimeFilter\n },\n }\n\nclass EventsView(viewsets.ReadOnlyModelViewSet):\n ...\n filter_class = EventFilter\n\nYou then won't have to worry about setting a different filter for each lookup expression and each field.",
2016-08-10T00:19:40
Flaiming :

You can create specific FilterSet as follows:\nimport django_filters\nfrom rest_framework import filters\nfrom rest_framework import viewsets\n\nclass EventFilter(filters.FilterSet):\n timestamp_gte = django_filters.DateTimeFilter(field_name="timestamp", lookup_expr='gte')\n class Meta:\n model = Event\n fields = ['event_type', 'event_model', 'timestamp', 'timestamp_gte']\n\nclass EventsView(viewsets.ReadOnlyModelViewSet):\n ...\n filter_class = EventFilter\n\nThan you can filter by "/api/v1/events/?timestamp_gte=2016-01-02"\nEDIT: Just to clarify, this example uses django-filter library.",
2016-05-12T11:37:36
Bruno Rino :

IsoDateTimeFilter is very picky about the input format; instead of:\n\n\n2016-01-02 00:00+0000\n\n\nuse:\n\n\n2016-01-02T00:00:00Z\n",
2018-01-26T16:00:02
Cookie Zhang :

A better way is to filter datetime in get_queryset function\n\ndef get_queryset(self):\n queryset = Event.objects.all()\n start_date = self.request.query_params.get('start_date', None)\n end_date = self.request.query_params.get('end_date', None)\n if start_date and end_date:\n queryset = queryset.filter(timstamp__range=[start_date, end_date])\n",
2018-12-29T01:24:24
eggbert :

None of the answers worked for me but this did:\n\nclass EventFilter(filters.FilterSet):\n start = filters.IsoDateTimeFilter(field_name=\"start\", lookup_expr='gte')\n end = filters.IsoDateTimeFilter(field_name=\"end\", lookup_expr='lte')\n\n class Meta:\n model = Event\n fields = 'start', 'end',\n",
2020-05-06T13:40:23
Khuong Tran :

I don't know what is the case you are looking for. Basically, you can access the params from the views by\ndate_params = self.request.query_params.get('params_name').\nThen you can do\nEvent.objects.filter(date__lte=date_params, date__gte=date_params)",
2022-05-18T16:22:33
yy