Open In App

Pass Request Context to Serializer from ViewSet in Django Rest Framework

Last Updated : 03 Oct, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Django Rest Framework (DRF) is a powerful toolkit for building Web APIs in Django. One of the features that make DRF so flexible is its ability to pass context from the ViewSet to the Serializer. This context can be particularly useful when we need to include additional information in our serializer, such as request data or user information. In this article, we'll walk through creating a Django project, implementing token authentication, and passing request context to serializers from a ViewSet. This article will walk us through two approaches to pass the request context from the ViewSet to the Serializer in DRF, allowing for more dynamic and flexible behavior.

There are two main approaches to passing the request context to the serializer:

We will explore both approaches with examples to help us understand how to pass the request context to the serializer efficiently.

Pass Request Context to Serializer from ViewSet in Django Rest Framework

Create a New Django Project

django-admin startproject myproject
cd myproject
python manage.py startapp blog

Update settings.py

Add the app and rest framework to our INSTALLED_APPS in settings.py

Python
INSTALLED_APPS = [
    # ...
    'rest_framework',
    'blog',
  	# Add this for token authentication
    'rest_framework.authtoken',
]

Set Up Token Authentication

To enable token authentication, we need to configure DRF. Add the following settings in settings.py:

Python
# ...

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ],
}
oppll

Create the Post Model

In blog/models.py, define a simple Post model:

Python
from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.title

Run the migrations to create the database table:

python manage.py makemigrations
python manage.py migrate

Create a Serializer

In blog/serializers.py, create a serializer for the Post model: To utilize the request object inside the serializer, simply access it via self.context: We to pass any additional context we may need, including the request object, user, or custom parameters.

Python
from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'content']

    def save(self, *args, **kwargs):
        request = self.context.get('request')
        if request and request.user:
          	self.author = request.user
        return super().save(*args, **Kwargs)

Approach 1: Using the context Parameter in the ViewSet

This PostViewSet handles CRUD operations for the Post model, using PostSerializer and restricting access to authenticated users with IsAuthenticated. The get_serializer method is overridden to explicitly pass the request context (self.request) to the serializer via the context argument.

Python
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from rest_framework.permissions import IsAuthenticated

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [IsAuthenticated]

    def get_serializer(self, *args, **kwargs):
        # Pass the request context explicitly when instantiating the serializer
        kwargs['context'] = {'request': self.request}
        return super().get_serializer(*args, **kwargs)

Approach 2: Overriding get_serializer_context() in the ViewSet

This PostViewSet provides CRUD operations for the Post model, restricted to authenticated users with IsAuthenticated permission. It uses the PostSerializer and passes the request context to the serializer by overriding get_serializer_context(). This allows the serializer to access the request data.

Python
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
from rest_framework.permissions import IsAuthenticated

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [IsAuthenticated]

    def get_serializer_context(self):
        context = super().get_serializer_context()
        # Add request context
        context['request'] = self.request
        return context

Set Up URLs

In blog/urls.py, set up the URLs for the ViewSet:

Python
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from blog.views import PostViewSet

router = DefaultRouter()
router.register(r'posts', PostViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include(router.urls)),
]

Create Token Authentication for Users

To use token authentication, we'll need to create tokens for users. We can do this using the Django shell. First, create a superuser:

python manage.py createsuperuser
create

Then, enter the shell:

python manage.py shell

Inside the shell, create a token for the superuser:

Python
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token

user = User.objects.get(username='your_username')
token = Token.objects.create(user=user)
print(token.key)
createtoekn

Run the Server

python manage.py runserver

Create a Post:

Use a GET request to http://127.0.0.1:8000/posts/

1
Output

In the headers, add Authorization: Token your_token_key.

oppp

In the body, include a JSON object with title and content.

{
"title": "First Post",
"content": "This is the content of the first post."
}
token
Output

Fetch All Posts:

  • Use a GET request to http://127.0.0.1:8000/posts/.
  • Include the same authorization header.
get
Output

Conclusion

Passing request context from a ViewSet to a serializer in Django Rest Framework allows for greater flexibility and the ability to include dynamic data when serializing objects. By setting up token authentication, we’ve also ensured that only authenticated users can create or view posts. This setup not only highlights the powerful features of DRF but also provides a robust foundation for building scalable APIs in Django. With these tools, we can create rich, user-authenticated applications that meet our project's requirements.


Next Article
Article Tags :
Practice Tags :

Similar Reads