python
51 lines · 6 steps
Building a date-range FilterSet in Django
A django-filter FilterSet that combines explicit date bounds, quick-range presets, and a default ordering.
Explained by
highlit
1import django_filters
2from django import forms
3from django.utils import timezone
4
5from .models import Report
6
7
8class ReportFilter(django_filters.FilterSet):
9 created_after = django_filters.DateFilter(
10 field_name="created_at",
11 lookup_expr="date__gte",
12 label="From",
13 widget=forms.DateInput(attrs={"type": "date"}),
14 )
15 created_before = django_filters.DateFilter(
16 field_name="created_at",
17 lookup_expr="date__lte",
18 label="To",
19 widget=forms.DateInput(attrs={"type": "date"}),
20 )
21 period = django_filters.ChoiceFilter(
22 method="filter_period",
23 label="Quick range",
24 choices=[
25 ("7d", "Last 7 days"),
26 ("30d", "Last 30 days"),
27 ("ytd", "Year to date"),
28 ],
29 )
30 status = django_filters.MultipleChoiceFilter(choices=Report.Status.choices)
31
32 class Meta:
33 model = Report
34 fields = ["created_after", "created_before", "period", "status"]
35
36 def filter_period(self, queryset, name, value):
37 now = timezone.now()
38 if value == "7d":
39 start = now - timezone.timedelta(days=7)
40 elif value == "30d":
41 start = now - timezone.timedelta(days=30)
42 elif value == "ytd":
43 start = now.replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)
44 else:
45 return queryset
46 return queryset.filter(created_at__gte=start)
47
48 @property
49 def qs(self):
50 parent = super().qs
51 return parent.order_by("-created_at")
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Declarative filter fields map URL query parameters directly onto model lookups.
- 2A method filter lets you translate a friendly choice into arbitrary queryset logic.
- 3Overriding qs is the clean hook for applying a default ordering to every filtered result.
Related explainers
python
import re from collections import Counter from pathlib import Path
Ranking the top words in a PDF
text-processing
regex
counting
Intermediate
6 steps
python
import json import hashlib from datetime import timedelta
Idempotent payment endpoints in FastAPI
idempotency
redis
distributed-locking
Advanced
9 steps
python
from flask import Blueprint, jsonify, request, abort v1 = Blueprint("users_v1", __name__) v2 = Blueprint("users_v2", __name__)
Versioning a Flask API with Blueprints
api versioning
blueprints
rest
Intermediate
7 steps
python
import time import threading from enum import Enum from functools import wraps
Building a circuit breaker in Python
circuit-breaker
resilience
decorators
Advanced
7 steps
python
from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector from django.core.cache import cache from django.db.models import F from django.http import JsonResponse
Ranked full-text search in Django
full-text-search
debouncing
caching
Advanced
9 steps
python
import os from datetime import timedelta
Class-based config in a Flask app factory
configuration
app-factory
inheritance
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/building-a-date-range-filterset-in-django-explained-python-eee6/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.