Django vs Django REST Framework
Django is a full web framework: ORM, migrations, admin, auth, forms, templates. It has no API layer: a Django view returns whatever you build, and turning models into JSON, validating input, and handling auth for API clients is left to you. Django REST Framework (DRF) is that layer, built on Django’s request cycle, ORM and auth. The interview question is usually “what does DRF add?”, and the senior part is knowing where it costs you.
What DRF adds
| Piece | What it gives you | Note |
|---|---|---|
| Serializers | validation in, rendering out | drf/02, drf/03 |
APIView, viewsets |
request parsing, content negotiation | drf/04 |
| Routers, actions | URL conventions for CRUD and extras | drf/05 |
| Auth and permissions | token, session, JWT classes; per-view rules | drf/07, drf/06 |
| Throttling, pagination | API concerns Django lacks | drf/08, drf/09 |
| Filtering, schema | query params, OpenAPI | drf/10, drf/16 |
The same endpoint, both ways:
# Plain Django: you parse, validate and serialise by hand
def order_detail(request, pk):
order = get_object_or_404(Order, pk=pk, customer=request.user)
return JsonResponse({"id": order.pk, "total": str(order.total)})# DRF: the serializer and viewset do it, with auth and permissions declared
class OrderViewSet(viewsets.ReadOnlyModelViewSet):
serializer_class = OrderSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return Order.objects.filter(customer=self.request.user)get_queryset scoped to the user is the authorization: a viewset that
returns Order.objects.all() lets any authenticated user read any order.
What DRF costs
- Serialisation is slow on large lists.
ModelSerializerbuilds field objects and validates per instance; rendering thousands of rows can cost more than the query. Paginate, use flatter serializers, or.values()for hot read paths (drf/12). - Nested serializers hide N+1 queries until
select_related/prefetch_relatedare applied inget_queryset(N+1 in Django: select_related, prefetch_related, fetch modes). - It is synchronous at heart. Django runs async views, but DRF’s view and serializer layer is sync; an async API in a Django codebase means Django Ninja or plain async views instead.
DRF, Django Ninja or FastAPI
- DRF when the codebase is already Django and you want its ecosystem (admin, auth, permissions, browsable API) with the most mature tooling.
- Django Ninja when you are in Django but want Pydantic schemas, type hints and async views.
- FastAPI for a new standalone service with type-driven validation, native async and generated OpenAPI; you bring your own ORM and admin.
The deciding factor is almost always the existing codebase, not benchmarks.
Related
Interview angle 3
- “What does DRF add to Django?” - serializers for validation and
rendering, viewsets and routers for CRUD conventions, authentication and
permission classes, pagination, filtering, throttling and a browsable API.
Django alone has no API layer.
- Follow-up: where does authorization live in a viewset? In
get_queryset(scope rows to the user) and in permission classes; a viewset over.objects.all()is an IDOR.
- Follow-up: where does authorization live in a viewset? In
- “DRF or FastAPI for a new API?” - FastAPI for type-driven validation, native async and automatic OpenAPI; DRF when you are already in Django and want the ORM, admin and auth ecosystem. Django Ninja sits between them.
- “Where does DRF get slow?” - nested serializers causing N+1 queries, and serialisation cost on large lists. Fix the queryset first, then paginate or flatten the representation.