Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchiTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
The standard path to a CRUD API in Django REST Framework (DRF) is to define a serializer for a model, expose it through a ModelViewSet, and register that viewset with a router. The serializer controls which fields the API exposes and validates incoming data; the viewset supplies conventional create, list, retrieve, update, and delete actions; and the router generates their URL patterns. Authentication, permissions, and pagination still need deliberate configuration.
How do I build a CRUD API with Django REST Framework?
Start with a Django model, then add a serializer, a viewset, and a router. The example below uses a simple Task resource. Adapt its fields and access rules to the data your application actually intends to expose.
1. Install DRF and enable it
Install the package in the project’s active Python environment:
pip install djangorestframework
Add rest_framework to INSTALLED_APPS in your Django settings. Check the current DRF compatibility guidance against your installed Django and Python versions; supported releases change over time. The official overview lists Django 5.2, 6.0, and 6.1 and Python 3.10 through 3.15 as supported at the time of its October 7, 2026 documentation snapshot. See the DRF overview.
#1 Best Overall
2. Define the model
For example, an application might have a task model with a title, completion status, and owner. The model belongs in the Django app and should reflect the actual domain and ownership rules. Create and apply migrations after adding or changing it.
3. Create a serializer
A serializer defines the API representation and validates incoming values before they are used to create or update a model instance. Choose fields intentionally: exposing every model field can reveal internal or sensitive data, while writable fields can allow clients to alter values they should not control.
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ["id", "title", "completed"]
This example exposes only the task identifier, title, and completion status. It deliberately omits the owner. If ownership is required, assign it through trusted server-side logic rather than accepting an arbitrary owner from an untrusted request.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →4. Add a model-backed viewset
A ModelViewSet supplies the standard operations for a model-backed resource. Set its queryset and serializer, and define the permission policy for the data.
Rank #2
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticated
from .models import Task
from .serializers import TaskSerializer
class TaskViewSet(viewsets.ModelViewSet):
queryset = Task.objects.all()
serializer_class = TaskSerializer
permission_classes = [IsAuthenticated]
This is a starting point, not a complete per-user access design: the queryset shown is global to the model. If users may access only their own tasks, scope the queryset to the requesting user and set ownership during creation. Add object-level permission checks where individual-object rules require them.
5. Register the viewset with a router
A router maps a registered viewset to conventional list and detail URLs. Include its URLs in the project URL configuration.
from rest_framework.routers import DefaultRouter
from .views import TaskViewSet
router = DefaultRouter()
router.register("tasks", TaskViewSet, basename="task")
urlpatterns = router.urls
If these routes belong under an API prefix, include the router URLs from the project’s main URL configuration with the desired prefix. Router-generated patterns are convenient for conventional resource actions; you do not need to write a separate URL declaration for each standard operation.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
How do serializers, viewsets, and routers work together?
Each part has a distinct responsibility. The serializer governs representation and validation, the viewset connects those rules to model operations, and the router exposes the viewset through URL patterns.
| DRF component | What it does | Decision to make |
|---|---|---|
| Serializer | Converts model instances to API data and validates incoming data. | Which fields are readable or writable, and how should relationships be represented? |
| Viewset | Groups resource actions such as listing, retrieving, creating, updating, and deleting. | Do standard model actions fit, and what queryset and permission rules apply? |
| Router | Maps registered viewsets to conventional URL patterns. | Do conventional resource routes fit, or is a custom route clearer? |
Together, these abstractions reduce repeated URL and view code. Their conventions are useful when the API is ordinary CRUD, but they should not obscure special workflows or access rules.
How do I choose between a ModelViewSet and explicit views?
Use a ModelViewSet when a resource maps cleanly to standard CRUD actions and its routes follow a conventional resource pattern. It keeps related operations together and lets a router create their URL mappings.
Use explicit views and URL patterns when you need a custom workflow, unusual route structure, or behavior that does not fit the standard actions. The explicit approach makes each operation and URL declaration visible, at the cost of writing more of the routing and view structure yourself. DRF’s viewsets guide and routers guide describe these conventions.
Recommended Free Tools
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. A successful authentication does not, by itself, authorize access to a particular action or record. DRF explains this distinction in its permissions guide.
Set a permission policy
You can set permissions on an individual viewset, as in the example, or establish defaults in the DRF settings. Choose the policy according to the resource: some APIs allow public reads but restrict writes; others require authentication for every action. Do not assume that requiring a logged-in user also limits that user to their own records.
Scope collection access and object access
For user-owned records, filter the viewset queryset so list requests return only records the current user may see. Object-level permissions address access to an individual retrieved or modified record, but they do not automatically define the correct list queryset. DRF’s object permission checks also depend on the view flow reaching the object check; consult the permissions guide when wiring custom behavior.
Choose and configure authentication separately
DRF supports authentication classes that determine how request credentials are interpreted. Choose a mechanism suitable for the clients and deployment, then define permissions that express what authenticated and unauthenticated users may do. Authentication and authorization answer different questions, so configure and test both.
How should I paginate a growing collection?
Configure pagination before collection responses become unwieldy. Page-number pagination is a straightforward starting point; another pagination style may suit a product with different navigation or consistency requirements.
Best Value
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 20,
}
The page size above is an example configuration, not a universal recommendation. Adjust it to the resource and client needs. DRF paginates automatically when pagination is configured for generic views and viewsets. A plain APIView requires explicit pagination calls. See the pagination guide.
How do I test CRUD behavior and access rules?
Test the API at the request level, not just the serializer in isolation. DRF provides test helpers and clients for exercising requests; its testing guide covers the available tools.
- Create: submit valid data and verify the response and persisted record.
- Read: check both collection and detail responses, including pagination when enabled.
- Update: test the supported update forms and confirm clients cannot change protected fields.
- Delete: verify the expected result and ensure unauthorized users cannot remove records.
- Validation: submit missing, malformed, and disallowed values and check that the API rejects them appropriately.
- Authorization: test unauthenticated requests and users attempting to retrieve, update, or delete another user’s records.
When using session authentication, write requests need CSRF tokens. Include that condition in tests that exercise session-authenticated writes rather than treating a CSRF rejection as a CRUD failure.
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 →What else needs a project-specific decision?
A serializer, viewset, and router provide a foundation, not a complete deployment or API governance plan. Decide how the application will handle database transactions, schema changes and versioning, filtering and ordering, request limits, deployment, and its threat model. Add filtering support only when needed; django-filter is an optional package, not a requirement for basic CRUD.
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.

