Day-1 of Learning APIs
| Published by Sudip Shrestha(Author)
At the beginning of my journey to learn APIs, I explored various resources. Mostly, I prefer to learn from books, which is why I searched online for a book and found one titled Django for APIs by William S. Vincent. The reasons for me to choose this book were:
- I was already interested in Django and the scope of this book focused on Django.
- This book was specifically written to help beginners, addressing the lack of good resources available for developers new to the Django REST Framework.
- It also includes many projects, and the author has made the code publicly available on GitHub (in case reader couldn't solve it)
LEARNING:
I found that in recent years an "API-first" approach has emerged as arguably the dominant paradigm in web development. This approach involves formally seperating the back-end from the front-end.
This paradigm of web-developement is "Future proof" because a backend API can be consumed by any JavaScript front-end(when the current front-end Framework eventually replaced by even newer ones in the years to come, the back-end API can remain the same) not only that when one expand from web to mobile app the change is only the front-end part we don't have to redesign the whole backend architecture for the newer frontend by simply attaching with the API.
Serilization
A serializer translates data into a format that is easy to consume over the internet, typically JSON, and is displayed at an API endpoint.Why Serializers are Important?
- APIs talk using JSON (or other formats).
- Django models are Python classes, not JSON.
- Serializers translate between these two worlds.
Types of Serializers in DRF
| Type | Meaning |
|---|---|
| serializer.serilizers | manually define field |
| serializer.ModelSerilizer | automatically define a field based on model |
- What Happens
Generics
In Django REST Framework (DRF), generics are a set of views that provide common functionality for working with API endpoints. They simplify the creation of common API views, such as listing, creating, retrieving, updating, or deleting resources. DRF provides a range of generic views for these operations, allowing developers to quickly create RESTful APIs without writing repetitive code. What are Generics in DRF? Generics are class-based views that come pre-built with common behaviors for handling standard database operations like retrieving, updating, and deleting model instances. These views are built on top of DRF's APIView and provide convenient methods to simplify CRUD operations. There are several generic views provided by DRF, and you can use them directly or extend them to meet your needs. Types of Generics in DRF Here are the main generic views available in DRF: ListCreateAPIView: Used for displaying a list of model instances and creating new ones. Provides functionality for GET (list of objects) and POST (create new object). RetrieveUpdateDestroyAPIView: Used for retrieving, updating, and deleting individual model instances. Provides functionality for GET (retrieve object), PUT/PATCH (update object), and DELETE (delete object).- ListAPIView: Used for displaying a list of model instances. Provides functionality for the GET method (list objects), but doesn't support creating new objects.
- CreateAPIView: Used for creating new model instances. Provides functionality for the POST method (create object), but doesn't support listing or modifying objects.
- RetrieveAPIView: Used for retrieving a single model instance. Provides functionality for the GET method (retrieve object), but doesn't support creating or modifying objects.
- DestroyAPIView: Used for deleting a single model instance. Provides functionality for the DELETE method (delete object), but doesn't support listing or creating objects.
- UpdateAPIView: Used for updating an existing model instance. Provides functionality for PUT/PATCH (update object), but doesn't support listing or creating objects.
Day-2 of Learning APIs
| Published by Sudip Shrestha(Author)
This sets the default permission policy for your API views. Examples: This sets how DRF will authenticate users. Common options: Used to paginate large lists of data automatically. Example: This splits large API responses into pages. DRF adds navigation links like: Other pagination classes: In Explanation: In If you need more custom behavior, you can use Once your views are defined, you need to wire them up in the URLs file ( With If you're using Once everything is set up, you can test the API by running the development server: Visit
Installed django rest-framework
pip install djangorestframework
REST_FRAMEWORK Settings
You can define a REST_FRAMEWORK dictionary in your settings.py file to customize how DRF behaves across your entire project.
# settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
],
# Optional: Pagination
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
}
1. DEFAULT_PERMISSION_CLASSES
'rest_framework.permissions.AllowAny': Anyone can access the API.'rest_framework.permissions.IsAuthenticated': Only authenticated users can access.'rest_framework.permissions.IsAdminUser': Only admin users can access.'rest_framework.permissions.DjangoModelPermissions': Uses Django's built-in model permissions.2. DEFAULT_AUTHENTICATION_CLASSES
'rest_framework.authentication.SessionAuthentication': Uses Django sessions (for browser users).'rest_framework.authentication.BasicAuthentication': HTTP Basic Auth (not safe for production unless HTTPS).'rest_framework.authentication.TokenAuthentication': For token-based auth (requires rest_framework.authtoken).'rest_framework_simplejwt.authentication.JWTAuthentication': For JWT tokens (third-party).3. DEFAULT_PAGINATION_CLASS and PAGE_SIZE
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10{
"next": "http://.../api/posts/?page=2",
"previous": null,
"results": [...]
}
LimitOffsetPaginationCursorPaginationOptional Settings You Might Use Later:
Creating Views and Serializers for API
1. serializers.py
serializers.py, you'll define how the data will be serialized (converted into JSON format). A serializer is similar to a Django Form or ModelForm.
# api/serializers.py
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__' # Serialize all fields of the Post model
ModelSerializer: This is the most common serializer that automatically generates fields based on the Django model.fields = '__all__': This indicates that you want to serialize all the fields in the model. You can also specify specific fields, e.g., ['title', 'content'].2. views.py
views.py, you'll define the API views. DRF provides several ways to create views, including APIView, viewsets, and generic views.Option 1: Using ViewSets (Recommended for simplicity)
ViewSets allow you to handle basic CRUD operations automatically.
# api/views.py
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all() # Query to get all posts
serializer_class = PostSerializer # Specify the serializer to use
ModelViewSet: Automatically provides implementations for CRUD operations (Create, Read, Update, Delete).Option 2: Using APIView (Custom behavior)
APIView to manually define the logic for each method (GET, POST, PUT, DELETE).
# api/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Post
from .serializers import PostSerializer
class PostList(APIView):
def get(self, request, format=None):
posts = Post.objects.all() # Fetch all posts
serializer = PostSerializer(posts, many=True) # Serialize the data
return Response(serializer.data) # Return as JSON
def post(self, request, format=None):
serializer = PostSerializer(data=request.data) # Get data from request
if serializer.is_valid():
serializer.save() # Save to database
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
get(): Retrieves data.post(): Creates new data.3. URLs Setup
urls.py).Using ViewSet (DRF Router)
viewsets, DRF provides a router that automatically maps the views to URLs.
# api/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet
router = DefaultRouter()
router.register(r'posts', PostViewSet) # Register PostViewSet for 'posts' endpoint
urlpatterns = [
path('', include(router.urls)), # Includes all routes from the router
]
Using APIView
APIView, manually create URL mappings.
# api/urls.py
from django.urls import path
from .views import PostList
urlpatterns = [
path('posts/', PostList.as_view(), name='post-list'), # Map to PostList class
]
4. Example of Testing the API
python manage.py runserver
http://127.0.0.1:8000/api/posts/ to see the list of posts (if you're using PostViewSet) or http://127.0.0.1:8000/api/posts for the APIView.
Day-3 of Learning APIs
| Published by Sudip Shrestha(Author)
What I Learned About Django REST Framework (DRF) and API Integration
- DRF returns data in JSON format
Example:[ { "id": 1, "title": "Task 1", "body": "Learn Django" }, { "id": 2, "title": "Task 2", "body": "Learn React" } ] - Django automatically adds an
idfield
This helps React identify each item using a uniquekeywhen rendering a list. - You use HTTP GET to access data from DRF
Called using:axios.get('http://127.0.0.1:8000/api/') - API endpoint design matters
Keeping it clean like/api/helps frontend-backend communication. - CORS must be enabled
React (on port 3000) and Django (on 8000) are separate origins, so CORS must be set using:django-cors-headers - API integration keeps content dynamic
React doesn't hardcode data — it fetches the live list from Django. - DRF (backend) and React (frontend) work together
DRF handles logic/data, React handles UI — and APIs connect them.
What is CORS?
CORS (Cross-Origin Resource Sharing) is a security feature enforced by web browsers. It determines whether a web application running on one origin (domain) is permitted to request resources from a different origin.
Purpose: Prevent unauthorized cross-domain requests for security.
Common Headers:
Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers
Example: A frontend hosted on https://example.com trying to access data from https://api.othersite.com requires CORS headers from the API server.
How to Handle CORS in Django
Use the django-cors-headers package:
1. Install the package
pip install django-cors-headers
2. Add to INSTALLED_APPS in settings.py
'corsheaders',
3. Add middleware (near the top)
'corsheaders.middleware.CorsMiddleware',
4. Allow all origins (for development)
CORS_ALLOW_ALL_ORIGINS = True
5. Or allow specific origins (recommended for production)
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"https://your-frontend.com",
]
Note: Only browser-based requests are affected by CORS. Server-to-server requests don't require it.
Day-4 of Learning APIs
| Published by Sudip Shrestha(Author)
Today I Learned: Custom Permissions in Django REST Framework
Django REST Framework ships with several out-of-the-box permission settings that we can use to secure our API. These permissions can be applied at different levels:
- Project-level: Set globally via
settings.py - View-level: Applied to specific views or viewsets
- Model-level: Enforced per-object using custom logic
Today, I learned how to create my own custom permission for my current project — a Blog site. I implemented a permission that ensures only the author of a blog post has the ability to update or delete it.
What This Means
By writing a custom permission class and attaching it to my viewset, I've added a layer of security to make sure that users cannot modify blog posts that they don't own. This enhances data integrity and user accountability in my app.
Custom Permissions in Django REST Framework (DRF)
What Are Custom Permissions?
Custom permissions in DRF let you define fine-grained access control for your API endpoints,
going beyond the built-in permissions like IsAuthenticated or IsAdminUser.
How BasePermission Works
- BasePermission is an abstract class you subclass to create custom permissions.
has_permission(self, request, view): checks general (view-level) access.has_object_permission(self, request, view, obj): checks object-specific access (e.g., for retrieve/update/delete).- DRF calls
has_permission()first, thenhas_object_permission()if the view is detail-based.
How to Create a Custom Permission
# app_name/permissions.py
from rest_framework.permissions import BasePermission
class IsOwnerOrReadOnly(BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in ['GET', 'HEAD', 'OPTIONS']:
return True
return obj.owner == request.user
How to Use a Custom Permission in a View
# app_name/views.py
from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer
from .permissions import IsOwnerOrReadOnly
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsOwnerOrReadOnly]
Combining With Built-in Permissions
from rest_framework.permissions import IsAuthenticated
class ArticleViewSet(viewsets.ModelViewSet):
...
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
Optional: Set as Global Default in settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
'your_app.permissions.IsOwnerOrReadOnly',
]
}
You can build more advanced permissions using custom logic inside the permission class.
Day-5 of Learning APIs
| Published by Sudip Shrestha(Author)
🔐 Introduction to User Authentication
User authentication is the process of verifying the identity of a user who is trying to access a system. It ensures that only registered and authorized users can access certain features, data, or services within a web or mobile application.
Since HTTP is stateless, servers cannot remember user sessions across multiple requests. To overcome this, authentication mechanisms are used to identify users in each interaction with the server.
Common user authentication actions include:
- Sign Up – Creating a new user account
- Log In – Verifying user credentials to gain access
- Log Out – Ending an authenticated session
Web applications and APIs support various authentication methods such as Basic Auth, Session Auth, Token Auth, JWT, and OAuth2, each with their own use cases and security considerations.
User Authentication Methods in Django REST Framework
1. Basic Authentication
Concept: Sends the username and password in every HTTP request using the Authorization header.
Workflow:
- Client sends a request.
- Server responds with
401 Unauthorized. - Client resends the request with encoded credentials.
- Server checks and responds with
200 OKor403 Forbidden.
Pros: Simple setup.
Cons: Insecure unless HTTPS is used. Credentials sent on every request.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
]
}
2. Session Authentication
Concept: Credentials are sent once; then a session ID is stored in a cookie for further requests.
Workflow:
- User logs in with username and password.
- Server creates a session object and returns a session ID cookie.
- Browser sends this cookie on every request.
- Server validates the session ID and grants access.
Pros: More secure and efficient than Basic Auth for web apps.
Cons: Not suitable for APIs across multiple devices or clients.
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
]
}
3. Token Authentication
Concept: User gets a token after login and includes it in the header of every request.
Workflow:
- User logs in with credentials.
- Server returns a token.
- Client sends token with each request using
Authorization: Token <token>.
Pros: Stateless, secure, works for APIs across platforms.
Cons: Requires token storage and revocation handling.
4. JWT (JSON Web Token)
Concept: A self-contained token with user info and expiry, sent with every request.
Workflow:
- User logs in and receives a JWT.
- Client sends JWT in
Authorization: Bearer <jwt>header. - Server verifies and decodes the token.
Pros: Stateless, scalable, secure with expiry and compact structure.
Cons: Cannot be revoked easily without extra tools.
5. OAuth 2.0
Concept: User logs in through a third-party (like Google), receives a token used to access protected resources.
Workflow:
- User authenticates through a provider (Google, Facebook, etc.).
- Provider returns an access token.
- Client uses this token to authenticate or fetch data.
Pros: Very secure, no handling of credentials, suitable for social logins.
Cons: Complex to set up, external dependency.
Summary Table
| Authentication Type | Stateful? | Secure? | Use Case |
|---|---|---|---|
| Basic Auth | No | Only with HTTPS | Testing or internal APIs |
| Session Auth | Yes | Yes | Django web apps |
| Token Auth | No | Yes | APIs across platforms |
| JWT | No | Yes (with expiry) | Modern APIs |
| OAuth 2.0 | No | Yes | Social login, external APIs |