Quick Start¶
This guide will help you get started with drf-restflow.
About This Guide¶
drf-restflow is a declarative library for Django REST Framework with multiple planned features. This quickstart focuses on Filtering - the first available feature.
What you'll learn: - Creating FilterSets with type annotations - Integrating filters into DRF views - Using query parameters for filtering and ordering
Future releases will add: - Declarative Annotated Serializer - FastAPI-Style Views - Advanced Caching
Let's build your first FilterSet!
Prerequisites¶
Make sure you have:
- Django and DRF installed and configured
- A Django model to filter
- Basic understanding of Django REST Framework
Examples¶
Let's quickly view the features of drf-restflow
FilterSet¶
Filterset helps you create a filter domain and helps filter queryset.
Define Your Model¶
Let's start with a simple Product model:
# models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.CharField(max_length=100)
in_stock = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
Create a FilterSet¶
Now create a FilterSet to enable filtering:
# filters.py
from restflow.filters import FilterSet, StringField, IntegerField, BooleanField
class ProductFilterSet(FilterSet):
# Explicit field declarations with lookups
name = StringField(lookups=["icontains"])
price = IntegerField(lookups=["comparison"]) # gt, gte, lt, lte
# Type annotation style
category: str
in_stock: bool
class Meta:
model = Product
order_fields = [("price", "price"), ("name", "name"), ("created_at", "created_at")]
Use in a View¶
Function-Based View¶
# views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .filters import ProductFilterSet
from .models import Product
@api_view(['GET'])
def product_list(request):
# Get base queryset
queryset = Product.objects.all()
# Apply filters
filterset = ProductFilterSet(request=request)
filtered_queryset = filterset.filter_queryset(queryset)
# Return response
return Response({
'count': filtered_queryset.count(),
'results': list(filtered_queryset.values())
})
Class-Based View¶
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .filters import ProductFilterSet
from .models import Product
class ProductListView(APIView):
def get(self, request):
queryset = Product.objects.all()
filterset = ProductFilterSet(request=request)
filtered_queryset = filterset.filter_queryset(queryset)
return Response({
'count': filtered_queryset.count(),
'results': list(filtered_queryset.values())
})
With DRF Generic Views¶
# views.py
from rest_framework import generics
from .filters import ProductFilterSet
from .models import Product
from .serializers import ProductSerializer
class ProductListAPIView(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get_queryset(self):
queryset = super().get_queryset()
filterset = ProductFilterSet(request=self.request)
return filterset.filter_queryset(queryset)
Add URL Pattern¶
# urls.py
from django.urls import path
from .views import product_list
urlpatterns = [
path('products/', product_list, name='product-list'),
]
Test Your API¶
Now you can filter products using query parameters:
Basic Filtering¶
# Get all products
GET /api/products/
# Filter by exact category
GET /api/products?category=electronics
# Filter by name containing "laptop"
GET /api/products?name__icontains=laptop
# Filter in-stock products
GET /api/products?in_stock=true
Range Filtering¶
# Products with price greater than or equal to 100
GET /api/products?price__gte=100
# Products with price less than 500
GET /api/products?price__lt=500
# Products in price range 100-500
GET /api/products?price__gte=100&price__lte=500
Negation (Exclusion)¶
# Exclude electronics category
GET /api/products?category!=electronics
# Products NOT named "laptop"
GET /api/products?name!=laptop
# Out of stock products
GET /api/products?in_stock!=true
Ordering¶
# Order by price ascending
GET /api/products?order_by=price
# Order by price descending
GET /api/products?order_by=-price
# Order by multiple fields
GET /api/products?order_by=category,-price
Combined Filtering¶
# Complex filter: laptops under $1000, in stock, ordered by price
GET /api/products?name__icontains=laptop&price__lte=1000&in_stock=true&order_by=price
Understanding the Generated Fields¶
The FilterSet automatically generates multiple filter fields:
| Declaration | Generated Fields |
|---|---|
name = StringField(lookups=["icontains"]) |
name, name__icontains, name!, name__icontains! |
price = IntegerField(lookups=["comparison"]) |
price, price__gt, price__gte, price__lt, price__lte, price!, price__gt!, ... |
category: str |
category, category! |
in_stock: bool |
in_stock, in_stock! |
Validation¶
The FilterSet automatically validates query parameters:
# Invalid integer
GET /api/products?price__gte=invalid
# Response: {"price__gte": ["A valid integer is required."]}
# Invalid boolean
GET /api/products?in_stock=maybe
# Response: {"in_stock": ["Must be a valid boolean."]}
Next Steps¶
Congratulations! You've created your first FilterSet with drf-restflow. Here's what to explore next:
Dive Deeper into Filtering: - Basic Concepts - Understand the library's philosophy - Filtering Tutorial - Complete walkthrough with real examples - FilterSet Guide - Comprehensive FilterSet documentation - Fields Guide - All field types, lookups, and PostgreSQL features
Stay Updated: - Watch the GitHub repository for new releases - Future features: Declarative Annotations, FastAPI-Style Views, Advanced Caching