API Thinking
Learn how clients and servers communicate through request/response contracts.
DRF (Django REST Framework) is the standard toolkit for building APIs in Django projects. It gives you a clean structure for handling request parsing, validation, business logic, authentication, permissions, and response formatting. In real projects, DRF helps you move from “just returning JSON” to a consistent API architecture that frontend apps, mobile clients, and third-party integrations can trust.
After this chapter, you should be able to explain how an API request flows through a DRF app, identify when to use each HTTP method, interpret status codes correctly, and understand core DRF concepts such as serializers, views, and authentication.
API Thinking
Learn how clients and servers communicate through request/response contracts.
REST Principles
Understand resources, endpoints, and stateless architecture.
DRF Building Blocks
Connect serializers, views, and routers into a maintainable API.
Install DRF in your Django project:
uv add djangorestframeworkRegister DRF in Django settings:
# settings.pyINSTALLED_APPS = [ # other apps "rest_framework",]Add baseline REST framework configuration:
# settings.pyREST_FRAMEWORK = { # Keep decimals as numbers in JSON responses instead of converting to strings (optional, but often desirable for APIs that return numeric data) 'COERCE_DECIMAL_TO_STRING': False,}An API (Application Programming Interface) is a formal communication layer between software systems. Instead of exposing internal database structure or application code directly, an API exposes carefully designed endpoints. Each endpoint accepts specific inputs and returns structured outputs, allowing different systems to work together without tightly coupling their implementations.
In practical terms, an API is a contract. The client agrees to send requests in a known format, and the server agrees to process those requests and return predictable responses. This contract allows teams to work independently: backend engineers can evolve internals while frontend engineers continue integrating through stable API definitions.
The following diagram represents the exact flow you shared, translated to Mermaid syntax:
This flow is the heart of backend API design. The client asks for a resource, the API server validates and processes that request, the database provides persisted data, and the API formats a response. DRF sits in the API server layer and gives you reusable tools for input validation, serialization, authentication, and permission checks.
REST (Representational State Transfer) is an architectural style, not a strict protocol. A RESTful API organizes data into resources and exposes them through URLs. Clients interact with those resources using HTTP methods such as GET, POST, PUT, PATCH, and DELETE.
A key REST idea is statelessness. Every request should carry all required context (authentication token, parameters, payload), so the server does not depend on hidden conversation state between calls. Stateless design improves scalability and makes APIs easier to cache, test, and debug.
HTTP methods communicate intent. Choosing the right method makes your API predictable and easy to consume.
GET retrieves data and should not change server state. It is considered a safe method and is commonly cached by browsers and proxies.
POST creates new resources or triggers non-idempotent operations. Repeating the same POST usually creates multiple records unless you implement deduplication.
PUT typically replaces the full resource representation, while PATCH partially updates selected fields. DRF supports both, and serializers help validate either full or partial payloads.
DELETE removes a resource (or marks it deleted in soft-delete designs). A successful deletion often returns 204 No Content.
Status codes describe result semantics. They are not optional decoration; they are part of the API contract and guide client-side behavior.
| Status Code | Meaning | Typical DRF Scenario |
|---|---|---|
| 200 OK | Request succeeded and response body is present | List or retrieve endpoint |
| 201 Created | New resource successfully created | Successful POST create |
| 204 No Content | Request succeeded with empty response body | Successful DELETE |
| 400 Bad Request | Input failed validation | Serializer errors |
| 401 Unauthorized | User is not authenticated | Missing/invalid auth token |
| 403 Forbidden | User is authenticated but not allowed | Permission denied |
| 404 Not Found | Resource does not exist | Invalid object ID |
| 500 Internal Server Error | Unexpected server failure | Unhandled backend exception |
JSON (JavaScript Object Notation) is the default data format for most REST APIs because it is language-agnostic, lightweight, and easy to parse in browsers, mobile apps, and backend services. In DRF, serializers convert Django model instances into JSON-compatible Python primitives, then renderers encode that data into JSON responses.
A good JSON payload is stable, explicit, and documented. Field naming, nullability, nested structure, and data types should remain consistent over time so clients do not break unexpectedly.
{ "id": 1, "name": "Kumar Sahil", "email": "krsahil8825@gmail.com", "is_active": true, "roles": ["admin", "editor"]}Serializer
Translates model/queryset data into JSON and validates incoming request data before saving.
APIView / ViewSet
Receives HTTP requests, applies authentication/permissions, calls serializer logic, and returns responses.
Router
Automatically generates URL patterns for ViewSets to keep API routing consistent.
Authentication
Verifies identity (who the user is), e.g., session, token, or JWT strategy.
Permission
Authorizes actions (what the user can do), e.g., read-only for anonymous users.
Pagination
Splits large result sets into pages for performance and better client UX.
| Endpoint | Method | Purpose |
|---|---|---|
/users/ | GET | Return paginated user list |
/users/ | POST | Create a new user |
/users/{id}/ | GET | Retrieve one user |
/users/{id}/ | PATCH | Partially update user |
/users/{id}/ | DELETE | Remove user |
Django: Focuses on server-rendered HTML views, forms, and template rendering. It is ideal for traditional web applications where the server generates the entire page. Django’s views and forms are designed around this request-response cycle.
DRF: Focuses on building APIs that return structured data (usually JSON) for consumption by clients like SPAs, mobile apps, or third-party services. DRF provides serializers for data validation and transformation, and views that handle API-specific logic like authentication and permissions.
Use Django views and templates when building a monolithic web application where the server renders HTML pages directly to users.
Use DRF when you need to expose an API for frontend frameworks (React, Vue), mobile apps, or third-party integrations. DRF allows you to build a clean separation between your backend logic and how clients consume data.
Django and DRF both have own request and response objects. DRF’s Request extends Django’s HttpRequest to provide additional functionality for parsing request data, handling authentication, and managing content negotiation. Similarly, DRF’s Response extends Django’s HttpResponse to simplify returning JSON responses with appropriate status codes and content types.
To use DRF’s Request and Response, you typically import them from rest_framework and use them in your API views. For example:
# views.pyfrom rest_framework.views import APIViewfrom rest_framework.response import Response
@api_view()def my_api_view(request): # DRF's Request object is used here data = {"message": "Hello, DRF!"} # DRF's Response object is used to return JSON data return Response(data)api_view DecoratorThe @api_view decorator is a function provided by DRF that allows you to create function-based API views. It takes a list of HTTP methods (e.g., ['GET', 'POST']) that the view should respond to. When you use @api_view, DRF automatically wraps your function in a way that it can handle API requests and responses, including content negotiation, authentication, and permission checks.
Default api view accepts only GET method, so if you want to allow other methods like POST, PATCH, etc., you need to specify them in the decorator. For example:
from rest_framework.decorators import api_view
@api_view(['GET', 'POST'])def my_api_view(request): if request.method == 'GET': # Handle GET request pass elif request.method == 'POST': # Handle POST request passstatus ModuleThe status module in DRF provides a set of named constants for HTTP status codes. Instead of remembering numeric codes like 200, 404, or 500, you can use descriptive names like status.HTTP_200_OK, status.HTTP_404_NOT_FOUND, and status.HTTP_500_INTERNAL_SERVER_ERROR. This improves code readability and makes it clear what each response status represents.
When returning a response in DRF, you can use the status module to set the appropriate status code. For example:
from rest_framework import statusfrom rest_framework.response import Responsedef my_api_view(request): data = {"message": "Hello, DRF!"} return Response(data, status=status.HTTP_200_OK)