Complete worked example
python
from drf_lab import setup
setup()
import django_filters
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, generics, serializers
from rest_framework.test import APIRequestFactory
from drf_lab import reset_fixture
from drf_lab.models import Role
class RoleFilter(django_filters.FilterSet):
country = django_filters.ChoiceFilter(choices=[(c, c) for c in ["US", "IL", "UA", "CA"]])
slots_min = django_filters.NumberFilter(field_name="slots", lookup_expr="gte")
class Meta:
model = Role
fields = ["country", "slots_min"]
class PublicRole(serializers.ModelSerializer):
class Meta:
model = Role
fields = ["id", "title", "country"]
class RoleList(generics.ListAPIView):
serializer_class = PublicRole
queryset = Role.objects.filter(owner__username="alice").order_by("id")
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_class = RoleFilter
search_fields = ["title"]
ordering_fields = ["id", "title", "slots"]
def inspect_example(query):
reset_fixture()
response = RoleList.as_view()(APIRequestFactory().get("/roles/", query))
body = {key: [e.code for e in values] for key, values in response.data.items()} if response.status_code >= 400 else [row["id"] for row in response.data]
return {"status": response.status_code, "body": body}- Reasoning
- DjangoFilterBackend applies the declared FilterSet and reports invalid country choices. SearchFilter uses the configured title field, while OrderingFilter allows only id, title and slots. The serializer emits a small public representation after those query operations. Tests combine country and minimum slots, exercise search, and reject an unsupported country. The local query uses real model rows and the helper reports exact returned IDs. A fixed title can appear in several employers in production, so this example does not pretend that search terms are vacancy identities.