What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
To build a CRUD REST API with Django REST Framework (DRF), define a serializer for the resource, connect it to a ModelViewSet, register that viewset with a router, and decide explicitly who may read or change the data. This pattern gives you conventional list, detail, create, update, and delete endpoints without repeating a view and URL declaration for each action.
How do I build a CRUD API with Django REST Framework?
The examples below use a simple task resource. Replace the model and fields with those in your project; in particular, expose only fields that clients should be able to read or submit.
As an Amazon Associate I earn from qualifying purchases.
1. Install DRF and enable it
Install the package in the project’s active Python environment, then add rest_framework to the Django settings file’s INSTALLED_APPS list:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →python -m pip install djangorestframework
Check the official DRF overview for compatibility with the Django and Python versions in your environment; supported versions change over time. Add optional packages such as django-filter only when the API needs their functionality.
#1 Best Overall
2. Define the model and serializer
A serializer determines how a resource is represented in API responses and how submitted data is validated and converted into model values. Choose fields deliberately: fields included in a serializer may become part of your API’s public representation.
# models.py
from django.conf import settings
from django.db import models
class Task(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
# serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ["id", "title", "complete", "created_at"]
read_only_fields = ["id", "created_at"]
Here, owner is intentionally not writable or returned through the serializer. The view will assign it from the authenticated request, preventing a client from choosing another user as the owner by submitting an ID.
3. Add a model-backed viewset
A ModelViewSet provides the standard model-backed actions. Set its queryset, serializer, and permission policy. Scope the queryset to the current user so that list responses and object lookups are limited to that user’s tasks.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Rank #2
# views.py
from rest_framework import permissions, viewsets
from .models import Task
from .serializers import TaskSerializer
class TaskViewSet(viewsets.ModelViewSet):
serializer_class = TaskSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Task.objects.filter(owner=self.request.user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
IsAuthenticated requires an authenticated request. The user-scoped queryset separately limits which task records the view can list or retrieve, update, and delete. If a resource has different visibility rules, encode them in the queryset and permission policy rather than relying on the serializer alone.
4. Register the viewset with a router
Routers map registered viewsets to conventional URL patterns. Include the router’s URLs in the project’s URL configuration:
# app urls.py
from rest_framework.routers import DefaultRouter
from .views import TaskViewSet
router = DefaultRouter()
router.register("tasks", TaskViewSet, basename="task")
urlpatterns = router.urls
# project urls.py
from django.urls import include, path
urlpatterns = [
path("api/", include("tasks.urls")),
]
With this registration, the resource has collection and detail routes under /api/tasks/. The router connects HTTP methods to the viewset’s standard actions; consult the DRF router guide for route details and options.
How do serializers, viewsets, and routers work together?
Each abstraction has a distinct job. The router selects a viewset action based on the URL and HTTP method; the viewset applies the queryset, permission checks, and action logic; the serializer validates incoming fields or renders the response representation.
| Component | Responsibility | Design decision |
|---|---|---|
| Serializer | Converts between model data and API representations; validates submitted values. | Which fields are exposed, writable, read-only, or represented as relationships. |
| Viewset | Implements resource actions and applies query and permission behavior. | Which records are available and whether standard CRUD actions match the workflow. |
| Router | Creates conventional URL mappings for registered viewsets. | Whether convention-based routes suit the resource or explicit routes are clearer. |
DRF’s quickstart demonstrates serializers, viewsets, routers, and pagination together. A quickstart illustrates framework mechanics; it does not establish the right field exposure or access policy for every application.
When should I use a ModelViewSet versus explicit views?
Choose based on how closely the resource matches ordinary CRUD and how much you want URL and action behavior to be explicit.
| Approach | Best fit | Trade-off |
|---|---|---|
ModelViewSet with a router |
A resource with conventional create, list, retrieve, update, and delete actions. | Concise and consistent, but URL-to-action behavior depends more on framework conventions. |
| Explicit views and URL patterns | Custom workflows, unusual routes, or endpoints whose behavior benefits from being visible in separate view and URL declarations. | More direct control and explicitness, with more code to define and maintain. |
You can also narrow a viewset’s available actions or add a distinct action for a workflow that does not fit standard CRUD. Use a separate explicit view or route when that makes the API’s behavior easier to understand. See the viewsets guide alongside the router guide.
How do I add authentication and permissions to a DRF API?
Authentication identifies the credentials associated with a request; permissions decide whether that request may proceed. Successful authentication does not, by itself, authorize access to every record or action. DRF’s authentication guide and permissions guide describe these separate responsibilities.
- Authentication: Choose and configure a mechanism appropriate to the clients and deployment. DRF supports multiple authentication schemes; the choice determines how request identity is established.
- View-level permission: Set the general rule for using the endpoint, such as requiring an authenticated user.
- Object-level access: Decide whether the requester may act on a particular record. Object permission checks run only when the view’s flow performs them; they do not automatically filter every collection response.
- Collection scoping: Filter the queryset when users should see only a subset of records. A per-object permission check alone does not express which objects belong in a list.
For user-owned data, combining an authenticated view with a queryset filtered by the request user is a straightforward starting point. More complex sharing, staff access, or organization membership needs explicit rules that match the application’s threat model.
Best Value
How should I paginate a growing collection?
Configure pagination before collection responses become unwieldy. Page-number pagination is an approachable option when clients can navigate numbered pages. Other pagination styles may better fit different navigation or consistency requirements.
# settings.py
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 25,
}
The page size above is an example configuration, not a universal recommendation. DRF applies configured pagination automatically to generic views and viewsets. A plain APIView requires explicit pagination calls. The pagination guide explains the available styles and configuration.
How do I test CRUD behavior and access rules?
Test the API as a client would use it, including both successful operations and rejected requests. DRF provides API testing helpers and test clients; its testing guide covers their use.
Free tools Windows power users keep installed
One-click scans. No signup required.
- Create a valid resource and check the returned representation and status.
- Read the collection and a detail record; verify the response includes only fields intended for clients.
- Update a permitted record, then verify the stored values and read-only field behavior.
- Delete a permitted record and confirm it is no longer available.
- Submit invalid data and check that validation errors identify the rejected fields.
- Make requests without credentials and verify the configured authentication and permission behavior.
- Authenticate as a different user and attempt to list, retrieve, update, or delete someone else’s record.
If you use session authentication for write requests, include the required CSRF token in the test request. The testing guide documents this requirement. Test list scoping as well as detail access: a record-level denial does not prove that another user’s record is absent from collection results.
What does this CRUD pattern leave for the application to decide?
A serializer, viewset, router, access policy, and pagination setting provide a useful API foundation, not a complete deployment or data-governance plan. The application still needs project-specific decisions about database transactions, schema and API versioning, filtering and ordering, rate limits, deployment topology, and its threat model. Recheck framework compatibility when upgrading because supported Django and Python versions change.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




