0% found this document useful (0 votes)
2 views36 pages

Classy Django REST Framework (DRF)

The document provides a comprehensive overview of Classy Django REST Framework (DRF), focusing on its class-based views (CBVs) and serializers. It details the main components including APIView, Generic Views, ViewSets, and Mixins, along with their key attributes and methods. Additionally, it offers examples for each component to illustrate their usage in building APIs.

Uploaded by

Md. Atiar Rahman
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views36 pages

Classy Django REST Framework (DRF)

The document provides a comprehensive overview of Classy Django REST Framework (DRF), focusing on its class-based views (CBVs) and serializers. It details the main components including APIView, Generic Views, ViewSets, and Mixins, along with their key attributes and methods. Additionally, it offers examples for each component to illustrate their usage in building APIs.

Uploaded by

Md. Atiar Rahman
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Ah!

You’re asking about Classy Django REST Framework (DRF) — basically, you want a
detailed breakdown of DRF’s class-based views (CBVs) and serializers, including their
methods and attributes. Let me explain carefully.

1️⃣ What is Classy Django REST Framework?


“Classy Django REST Framework” usually refers to DRF’s class-based approach to
building APIs. Instead of writing all logic in functions, DRF provides pre-built classes
(views, serializers, mixins, and generic views) that you can extend. This makes APIs
cleaner, reusable, and maintainable.

DRF’s main class-based components:

1. Views
APIView
Generic views ( ListAPIView , RetrieveAPIView , etc.)
ViewSets ( ModelViewSet , ReadOnlyModelViewSet )
2. Serializers
Serializer
ModelSerializer
HyperlinkedModelSerializer
3. Mixins
CreateModelMixin , ListModelMixin , etc.

2️⃣ DRF Class-Based Views (CBVs)


2.1 APIView

The base class for all DRF class-based views.

Inherits from Django’s View .


Provides content negotiation, authentication, permission handling, throttling, and
exception handling.

Key attributes:

authentication_classes → List of authentication classes (e.g.,


TokenAuthentication )
permission_classes → List of permission classes (e.g., IsAuthenticated )
throttle_classes → List of throttling classes
renderer_classes → Output format (JSON, Browsable API)
parser_classes → Input format (JSONParser, FormParser)

Key methods:

get(request, *args, **kwargs) → Handles GET requests


post(request, *args, **kwargs) → Handles POST requests
put(request, *args, **kwargs) → Handles PUT requests
patch(request, *args, **kwargs) → Handles PATCH requests
delete(request, *args, **kwargs) → Handles DELETE requests
initialize_request(request, *args, **kwargs) → Wraps Django request into
DRF Request
handle_exception(exc) → Handles exceptions

Example:

from rest_framework.views import APIView


from rest_framework.response import Response
from rest_framework import status

class HelloView(APIView):
def get(self, request):
return Response({"message": "Hello, World!"},
status=status.HTTP_200_OK)

2.2 Generic Views

These are DRF views that combine APIView + Mixins, so you don’t need to implement
standard CRUD operations manually.

Examples:

ListAPIView → Read-only list


RetrieveAPIView → Read-only detail
CreateAPIView → Create object
UpdateAPIView → Update object
DestroyAPIView → Delete object
ListCreateAPIView → List + Create
RetrieveUpdateDestroyAPIView → Retrieve + Update + Delete

Key attributes:
queryset → Default queryset for the view
serializer_class → Serializer class
lookup_field → Default: 'pk' , field for retrieving single objects

Key methods:

get_queryset() → Returns queryset, can be customized


get_serializer() → Returns serializer instance
perform_create(serializer) → Hook after creation
perform_update(serializer) → Hook after update
perform_destroy(instance) → Hook after deletion

Example:

from rest_framework import generics


from .models import Student
from .serializers import StudentSerializer

class StudentListCreateView([Link]):
queryset = [Link]()
serializer_class = StudentSerializer

2.3 ViewSets

A ViewSet allows combining all CRUD operations in one class. Often paired with routers.

Examples:

ViewSet → Basic, you define each action


ModelViewSet → All CRUD implemented automatically
ReadOnlyModelViewSet → Only GET (list/retrieve)

Key attributes:

queryset → Base queryset


serializer_class → Serializer class
lookup_field → Object lookup (default: 'pk' )

Key methods:

list(self, request, *args, **kwargs) → GET list


retrieve(self, request, *args, **kwargs) → GET detail
create(self, request, *args, **kwargs) → POST
update(self, request, *args, **kwargs) → PUT
partial_update(self, request, *args, **kwargs) → PATCH
destroy(self, request, *args, **kwargs) → DELETE

Example:

from rest_framework import viewsets


from .models import Student
from .serializers import StudentSerializer

class StudentViewSet([Link]):
queryset = [Link]()
serializer_class = StudentSerializer

3️⃣ DRF Serializers


Serializers in DRF convert complex data types (e.g., QuerySets) into Python primitives
(dict, list) for JSON, and vice versa.

3.1 Serializer

Base class for all serializers. You define fields manually.

Key attributes:

fields → Dictionary of fields


read_only_fields → Fields that cannot be updated
validators → Custom validators

Key methods:

create(validated_data) → Create instance


update(instance, validated_data) → Update instance
validate_<fieldname>(value) → Field-level validation
validate(attrs) → Object-level validation

Example:

from rest_framework import serializers


from .models import Student

class StudentSerializer([Link]):
id = [Link](read_only=True)
name = [Link](max_length=100)
age = [Link]()
def create(self, validated_data):
return [Link](**validated_data)

def update(self, instance, validated_data):


[Link] = validated_data.get('name', [Link])
[Link] = validated_data.get('age', [Link])
[Link]()
return instance

3.2 ModelSerializer

A shortcut for serializers tied to Django models.

Key attributes:

[Link] → Model class


[Link] → Fields to include
[Link] → Fields to exclude
Meta.read_only_fields → Fields that are read-only

Key methods: (inherits from Serializer )

create(validated_data) → Auto create model instance


update(instance, validated_data) → Auto update instance
to_representation(instance) → Customize output
to_internal_value(data) → Customize input parsing

Example:

from rest_framework import serializers


from .models import Student

class StudentModelSerializer([Link]):
class Meta:
model = Student
fields = ['id', 'name', 'age']

4️⃣ Mixins
Mixins provide small reusable behaviors that generic views use.
Mixin Purpose
CreateModelMixin Adds create() method
ListModelMixin Adds list() method
RetrieveModelMixin Adds retrieve() method
UpdateModelMixin Adds update() & partial_update()
DestroyModelMixin Adds destroy() method

They are usually combined with GenericAPIView .

✅ Summary of Classy DRF:


APIView → Base CBV for custom API logic
Generic Views → Pre-built CRUD views
ViewSets → All CRUD in one class, paired with routers
Serializers → Convert model/queryset to/from JSON
Mixins → Reusable pieces of functionality

If you want, I can make a single mega table listing all DRF CBVs and serializers with
every method and attribute in one place—this is super useful for interviews or quick
reference.

Do you want me to do that?

Perfect! Let’s go deep dive into all DRF generic class-based views you mentioned. I’ll
explain what each view does, its key attributes/methods, and give a complete example
for each.

1️⃣ GenericAPIView
GenericAPIView is the base class for all DRF generic views.
It combines APIView + Mixin support, providing features like:

Key attributes:

queryset → Base queryset for view


serializer_class → Serializer class for input/output
lookup_field → Field to retrieve single objects (default 'pk' )
pagination_class → Custom pagination if needed
filter_backends → For filtering/query params

Key methods:

get_queryset() → Return queryset, can be customized


get_serializer(*args, **kwargs) → Return serializer instance
get_object() → Retrieve single object
filter_queryset(queryset) → Apply filters

Example:

from rest_framework.generics import GenericAPIView


from rest_framework.response import Response
from .models import Student
from .serializers import StudentSerializer

class StudentGenericView(GenericAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

def get(self, request):


students = self.get_queryset()
serializer = self.get_serializer(students, many=True)
return Response([Link])

2️⃣ CreateAPIView
Purpose: Only supports POST requests (create new object)
Mixins used: CreateModelMixin + GenericAPIView

Key methods:

create(request, *args, **kwargs) → Create new instance


perform_create(serializer) → Hook after saving instance

Example:

from rest_framework.generics import CreateAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentCreateView(CreateAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage: POST /students/ with JSON body like {"name": "John", "age": 22}

3️⃣ DestroyAPIView
Purpose: Only supports DELETE requests
Mixins used: DestroyModelMixin + GenericAPIView

Key methods:

destroy(request, *args, **kwargs) → Delete object


perform_destroy(instance) → Hook before/after deletion

Example:

from rest_framework.generics import DestroyAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentDeleteView(DestroyAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage: DELETE /students/1/ deletes student with id=1 .

4️⃣ ListAPIView
Purpose: Only supports GET for listing objects
Mixins used: ListModelMixin + GenericAPIView

Key methods:

list(request, *args, **kwargs) → Return all objects


Supports pagination and filtering automatically

Example:

from rest_framework.generics import ListAPIView


from .models import Student
from .serializers import StudentSerializer
class StudentListView(ListAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage: GET /students/ → returns all students

5️⃣ ListCreateAPIView
Purpose: Supports GET (list) + POST (create)
Mixins used: ListModelMixin + CreateModelMixin + GenericAPIView

Example:

from rest_framework.generics import ListCreateAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentListCreateView(ListCreateAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage:

GET /students/ → list all


POST /students/ → create new student

6️⃣ RetrieveAPIView
Purpose: Only supports GET for single object detail
Mixins used: RetrieveModelMixin + GenericAPIView

Key methods:

retrieve(request, *args, **kwargs) → Return single object


get_object() → Retrieve object by lookup_field (default 'pk' )

Example:

from rest_framework.generics import RetrieveAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentDetailView(RetrieveAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage: GET /students/1/ → returns student with id=1

7️⃣ RetrieveDestroyAPIView
Purpose: Supports GET (retrieve) + DELETE (destroy)
Mixins used: RetrieveModelMixin + DestroyModelMixin + GenericAPIView

Example:

from rest_framework.generics import RetrieveDestroyAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentRetrieveDestroyView(RetrieveDestroyAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage:

GET /students/1/ → retrieve student


DELETE /students/1/ → delete student

8️⃣ RetrieveUpdateAPIView
Purpose: Supports GET + PUT/PATCH (update)
Mixins used: RetrieveModelMixin + UpdateModelMixin + GenericAPIView

Example:

from rest_framework.generics import RetrieveUpdateAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentRetrieveUpdateView(RetrieveUpdateAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage:

GET /students/1/ → retrieve


PUT/PATCH /students/1/ → update

9️⃣ RetrieveUpdateDestroyAPIView
Purpose: Supports GET + PUT/PATCH + DELETE
Mixins used: RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin +
GenericAPIView

Example:

from rest_framework.generics import RetrieveUpdateDestroyAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentRetrieveUpdateDestroyView(RetrieveUpdateDestroyAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage: GET/PUT/PATCH/DELETE /students/1/

10️⃣ UpdateAPIView
Purpose: Only supports PUT/PATCH (update object)
Mixins used: UpdateModelMixin + GenericAPIView

Example:

from rest_framework.generics import UpdateAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentUpdateView(UpdateAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

Usage: PUT/PATCH /students/1/ → update only

✅ Summary Table
View Purpose HTTP Methods Mixins
GenericAPIView Base class Custom -
CreateAPIView Create POST CreateModelMixin
object
DestroyAPIView Delete DELETE DestroyModelMixin
object
ListAPIView List objects GET ListModelMixin
ListCreateAPIView List + GET, POST List + Create
Create
RetrieveAPIView Retrieve GET RetrieveModelMixin
single
RetrieveDestroyAPIView Retrieve + GET, DELETE Retrieve + Destroy
Delete
RetrieveUpdateAPIView Retrieve + GET, Retrieve + Update
Update PUT/PATCH
RetrieveUpdateDestroyAPIView Retrieve + GET, Retrieve + Update +
Update + PUT/PATCH, Destroy
Delete DELETE
UpdateAPIView Update PUT/PATCH UpdateModelMixin
object

If you want, I can also make a diagram showing which mixins + GenericAPIView make
each of these classes, which is super easy to memorize for interviews.

Do you want me to make that diagram?

Perfect! Let’s go deep dive into all DRF mixins you mentioned. Mixins are small reusable
classes that provide specific functionality (CRUD operations) when combined with
GenericAPIView or other generic views.

1️⃣ CreateModelMixin
Purpose: Adds create functionality (usually POST)
Typically used with GenericAPIView

Key methods:
create(request, *args, **kwargs) → Handles creating an object
perform_create(serializer) → Hook after saving instance; you can override it

Example:

from rest_framework import mixins


from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework import status
from .models import Student
from .serializers import StudentSerializer

class StudentCreateView([Link], GenericAPIView):


queryset = [Link]()
serializer_class = StudentSerializer

def post(self, request, *args, **kwargs):


return [Link](request, *args, **kwargs)

Usage: POST /students/ → creates a new student

2️⃣ DestroyModelMixin
Purpose: Adds delete functionality (usually DELETE)
Typically used with GenericAPIView

Key methods:

destroy(request, *args, **kwargs) → Deletes object


perform_destroy(instance) → Hook before/after deletion

Example:

from rest_framework import mixins


from rest_framework.generics import GenericAPIView

class StudentDestroyView([Link], GenericAPIView):


queryset = [Link]()
serializer_class = StudentSerializer

def delete(self, request, *args, **kwargs):


return [Link](request, *args, **kwargs)

Usage: DELETE /students/1/ → deletes student with id=1


3️⃣ ListModelMixin
Purpose: Adds list functionality (GET all objects)
Supports pagination and filtering automatically

Key methods:

list(request, *args, **kwargs) → Returns serialized list of objects

Example:

from rest_framework import mixins


from rest_framework.generics import GenericAPIView

class StudentListView([Link], GenericAPIView):


queryset = [Link]()
serializer_class = StudentSerializer

def get(self, request, *args, **kwargs):


return [Link](request, *args, **kwargs)

Usage: GET /students/ → returns all students

4️⃣ RetrieveModelMixin
Purpose: Adds retrieve functionality (GET single object)

Key methods:

retrieve(request, *args, **kwargs) → Returns single object


Uses get_object() from GenericAPIView to find object

Example:

from rest_framework import mixins


from rest_framework.generics import GenericAPIView

class StudentRetrieveView([Link], GenericAPIView):


queryset = [Link]()
serializer_class = StudentSerializer

def get(self, request, *args, **kwargs):


return [Link](request, *args, **kwargs)

Usage: GET /students/1/ → returns student with id=1


5️⃣ UpdateModelMixin
Purpose: Adds update functionality (PUT/PATCH)

Key methods:

update(request, *args, **kwargs) → Update object


partial_update(request, *args, **kwargs) → Update partially (PATCH)
perform_update(serializer) → Hook after update

Example:

from rest_framework import mixins


from rest_framework.generics import GenericAPIView

class StudentUpdateView([Link], GenericAPIView):


queryset = [Link]()
serializer_class = StudentSerializer

def put(self, request, *args, **kwargs):


return [Link](request, *args, **kwargs)

def patch(self, request, *args, **kwargs):


return self.partial_update(request, *args, **kwargs)

Usage:

PUT /students/1/ → full update


PATCH /students/1/ → partial update

✅ Summary Table of Mixins


Mixin Purpose Methods Typical HTTP
method
CreateModelMixin Create new create() , POST
object perform_create()

DestroyModelMixin Delete destroy() , DELETE


object perform_destroy()

ListModelMixin List all list() GET


objects
RetrieveModelMixin Retrieve retrieve() GET
single object
Mixin Purpose Methods Typical HTTP
method
UpdateModelMixin Update update() , PUT/PATCH
object partial_update() ,
perform_update()

💡 Tip:
All DRF generic views ( ListAPIView , CreateAPIView ,
RetrieveUpdateDestroyAPIView , etc.) are basically pre-built combinations of these
mixins + GenericAPIView.

For example:

RetrieveUpdateDestroyAPIView = RetrieveModelMixin + UpdateModelMixin +


DestroyModelMixin + GenericAPIView

If you want, I can make a visual diagram showing all mixins + generic views
combination—so you can instantly memorize which mixins make which generic view.

Do you want me to do that?

Perfect! Let’s go deep dive into DRF pagination classes. Pagination in DRF controls how
large querysets are split into smaller “pages” when returned by your API.

1️⃣ BasePagination
Purpose: The abstract base class for all DRF pagination classes.
You never use this directly; instead, DRF provides subclasses like
PageNumberPagination , LimitOffsetPagination , and CursorPagination .

Key methods you can override:

paginate_queryset(queryset, request, view=None) → Returns a page of objects


get_paginated_response(data) → Returns the paginated response (usually includes
metadata like count , next , previous )

Example (custom pagination):


from rest_framework.pagination import BasePagination
from rest_framework.response import Response

class MyCustomPagination(BasePagination):
def paginate_queryset(self, queryset, request, view=None):
self.page_size = 2
[Link] = int(request.query_params.get('page', 1))
start = ([Link] - 1) * self.page_size
end = start + self.page_size
[Link] = len(queryset)
return queryset[start:end]

def get_paginated_response(self, data):


return Response({
'count': [Link],
'page': [Link],
'results': data
})

Usage in view:

from rest_framework.generics import ListAPIView


from .models import Student
from .serializers import StudentSerializer

class StudentListView(ListAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
pagination_class = MyCustomPagination

2️⃣ PageNumberPagination
Purpose: Classic pagination using page numbers
URL example: /students/?page=2

Key attributes:

page_size → Number of items per page (default: 10)


page_query_param → Query parameter for page number (default: 'page' )
page_size_query_param → Optional: allow client to change page size via query param
max_page_size → Maximum allowed page size

Example:
from rest_framework.pagination import PageNumberPagination

class StudentPageNumberPagination(PageNumberPagination):
page_size = 3
page_size_query_param = 'size'
max_page_size = 10

Usage in view:

class StudentListView(ListAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
pagination_class = StudentPageNumberPagination

GET /students/?page=2&size=3 → returns 3 students on page 2

3️⃣ LimitOffsetPagination
Purpose: Pagination using limit and offset query params
URL example: /students/?limit=5&offset=10

Key attributes:

default_limit → Default number of items if limit not provided


limit_query_param → Query param for limit (default: 'limit' )
offset_query_param → Query param for offset (default: 'offset' )
max_limit → Maximum allowed items per page

Example:

from rest_framework.pagination import LimitOffsetPagination

class StudentLimitOffsetPagination(LimitOffsetPagination):
default_limit = 3
max_limit = 10

Usage in view:

class StudentListView(ListAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
pagination_class = StudentLimitOffsetPagination
GET /students/?limit=3&offset=6 → returns 3 students starting from index 6

4️⃣ CursorPagination
Purpose: Pagination using a cursor (more secure & consistent for large datasets)
Uses encoded cursor based on ordering field instead of page numbers or offset
URL example: /students/?cursor=YXJyYXljb25uZWN0aW9uOjEw

Key attributes:

page_size → Number of items per page


cursor_query_param → Query param for cursor (default: 'cursor' )
ordering → Field used for ordering (required, e.g., 'id' or '-created' )

Example:

from rest_framework.pagination import CursorPagination

class StudentCursorPagination(CursorPagination):
page_size = 3
ordering = 'id' # cursor uses this field

Usage in view:

class StudentListView(ListAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
pagination_class = StudentCursorPagination

GET /students/?cursor=xyz → returns next page based on cursor

✅ Summary Table
Pagination Class Query Key Feature Use Case
Params
BasePagination Custom Abstract base, Advanced/custom
define your own logic pagination
PageNumberPagination page , Simple page number Small to medium
optional datasets
size
Pagination Class Query Key Feature Use Case
Params
LimitOffsetPagination limit , Offset-based, flexible APIs where clients want
offset control over slice
CursorPagination cursor Cursor-based, Large datasets, secure,
prevents duplicates consistent pagination
on data change

💡 Tips:
1. Use PageNumberPagination for simple apps.
2. Use LimitOffsetPagination if you need client-controlled page sizes.
3. Use CursorPagination for large datasets or real-time data, because offset-based
pagination can skip or repeat objects if data changes.

If you want, I can make a diagram showing all 4 pagination types, query params, and
examples of API responses, so it’s super easy to memorize.

Do you want me to do that?

Perfect! Let’s go deep dive into DRF serializers, including all the classes you mentioned.
I’ll explain what each is, their key attributes/methods, and give examples.

1️⃣ Serializer (Base Serializer)


Purpose: The base class for all serializers.
Converts complex Python objects (models, querysets) into primitive data types (dict,
list, etc.) that can be rendered into JSON or other content types, and validates input
data.

Key attributes:

fields → Dictionary of fields defined on the serializer


read_only_fields → Fields that cannot be updated
validators → Custom field or object-level validators

Key methods:
create(validated_data) → Create object from validated data
update(instance, validated_data) → Update object
validate_<fieldname>(value) → Field-level validation
validate(attrs) → Object-level validation
to_representation(instance) → Customize how object is converted to JSON
to_internal_value(data) → Customize how input data is parsed

Example:

from rest_framework import serializers


from .models import Student

class StudentSerializer([Link]):
id = [Link](read_only=True)
name = [Link](max_length=100)
age = [Link]()

def create(self, validated_data):


return [Link](**validated_data)

def update(self, instance, validated_data):


[Link] = validated_data.get('name', [Link])
[Link] = validated_data.get('age', [Link])
[Link]()
return instance

Usage: Works for custom objects or models without auto-mapping.

2️⃣ ModelSerializer
Purpose: Shortcut for serializers tied to Django models.
Automatically generates fields and create() / update() methods from the model.

Key attributes:

[Link] → Model class


[Link] → Fields to include
[Link] → Fields to exclude
Meta.read_only_fields → Read-only fields

Example:

from rest_framework import serializers


from .models import Student
class StudentModelSerializer([Link]):
class Meta:
model = Student
fields = ['id', 'name', 'age']

✅ ModelSerializer automatically handles create() and update() .

3️⃣ HyperlinkedModelSerializer
Purpose: Like ModelSerializer , but represents relationships with URLs instead of
primary keys.
Useful for RESTful APIs with hyperlinks.

Key attributes:

Same as ModelSerializer ( [Link] , fields )


Use HyperlinkedIdentityField for object URL

Example:

from rest_framework import serializers


from .models import Student

class
StudentHyperlinkedSerializer([Link]):
class Meta:
model = Student
fields = ['url', 'id', 'name', 'age']
extra_kwargs = {
'url': {'view_name': 'student-detail', 'lookup_field': 'pk'}
}

Usage: GET /students/1/ returns:

{
"url": "[Link]
"id": 1,
"name": "John",
"age": 22
}
4️⃣ ListSerializer
Purpose: Handles lists of objects; usually used internally by many=True in
ModelSerializer.
Can be customized for bulk create/update.

Key attributes/methods:

child → The serializer for individual items


create(validated_data) → Bulk create
update(instance, validated_data) → Bulk update

Example:

from rest_framework import serializers


from .models import Student

class StudentSerializer([Link]):
class Meta:
model = Student
fields = ['id', 'name', 'age']

class StudentListSerializer([Link]):
child = StudentSerializer()

def create(self, validated_data):


students = [Student(**item) for item in validated_data]
return [Link].bulk_create(students)

Usage:

serializer = StudentListSerializer(data=[{'name': 'John', 'age': 22},


{'name': 'Jane', 'age': 23}], many=True)
serializer.is_valid()
[Link]()

5️⃣ BaseSerializer
Purpose: The most low-level serializer, abstract class under Serializer .
Provides hooks for custom serialization logic, useful if you don’t want DRF to handle
validation automatically.

Key methods:
to_representation(instance) → Required: define how Python object becomes dict
to_internal_value(data) → Required: define how dict/JSON becomes Python object
is_valid(raise_exception=False) → Checks if input data is valid
save(**kwargs) → Calls create() or update()

Example:

from rest_framework.serializers import BaseSerializer


from .models import Student

class MyBaseStudentSerializer(BaseSerializer):
def to_representation(self, instance):
return {
'id': [Link],
'name': [Link](), # example of custom formatting
'age': [Link]
}

def to_internal_value(self, data):


return {
'name': [Link]('name').title(),
'age': [Link]('age')
}

def create(self, validated_data):


return [Link](**validated_data)

✅ Use BaseSerializer when you want full control over input/output without automatic
field mapping.

Summary Table of Serializers

Serializer Class Purpose Key Feature When to


Use
Serializer Base Manual fields + Custom
serializer validation objects, full
control
ModelSerializer Auto Auto create() & Standard
serializer for update() model APIs
models
HyperlinkedModelSerializer Model Related objects as RESTful
serializer URLs hyperlinked
with URLs APIs
Serializer Class Purpose Key Feature When to
Use
ListSerializer Handles Bulk create/update Bulk
many=True operations
BaseSerializer Most low- Must define Full control,
level to_representation & custom
to_internal_value serialization

💡 Tip:
Use ModelSerializer for almost all cases when working with Django models.
HyperlinkedModelSerializer is better if you want RESTful URLs.
ListSerializer is mainly used internally by DRF when you pass many=True , but you
can override it for bulk operations.
BaseSerializer is for advanced use cases.

If you want, I can make a diagram showing all serializer classes and how they relate
(BaseSerializer → Serializer → ModelSerializer → Hyperlinked/Lists), which makes it
super easy to memorize.

Do you want me to make that diagram?

Sure! Let’s go in-depth into DRF’s APIView , which is the foundation of all class-based
views in Django REST Framework.

APIView (DRF)
1️⃣ What is APIView ?

APIView is a class-based view provided by DRF that extends Django’s View.


It allows you to write RESTful endpoints with proper handling of HTTP methods,
authentication, permissions, throttling, and content negotiation.
All generic views and ViewSets in DRF are ultimately built on top of APIView .

Key points:

Handles request parsing ( Request object instead of Django’s HttpRequest )


Handles response rendering ( Response object instead of Django’s HttpResponse )
Supports authentication, permissions, throttling out of the box
Provides exception handling for API errors

2️⃣ Key Attributes of APIView

Attribute Purpose
authentication_classes List of authentication classes (e.g., TokenAuthentication )
permission_classes List of permission classes (e.g., IsAuthenticated )
throttle_classes Throttle classes to limit request rate
parser_classes Input parsers (JSON, Form, MultiPart)
renderer_classes Output renderers (JSON, Browsable API, etc.)

3️⃣ Key Methods of APIView

Method Purpose
get(request, *args, **kwargs) Handle GET request
post(request, *args, **kwargs) Handle POST request
put(request, *args, **kwargs) Handle PUT request
patch(request, *args, **kwargs) Handle PATCH request
delete(request, *args, **kwargs) Handle DELETE request
initialize_request(request, *args, Wrap Django request in DRF Request
**kwargs) object
handle_exception(exc) Handles exceptions and returns proper
HTTP response

4️⃣ Basic Example of APIView

Suppose you have a Student model:

# [Link]
from [Link] import models

class Student([Link]):
name = [Link](max_length=100)
age = [Link]()

APIView Example:

# [Link]
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Student
from .serializers import StudentSerializer

class StudentAPIView(APIView):

def get(self, request, *args, **kwargs):


# GET: return list of students
students = [Link]()
serializer = StudentSerializer(students, many=True)
return Response([Link])

def post(self, request, *args, **kwargs):


# POST: create new student
serializer = StudentSerializer(data=[Link])
if serializer.is_valid():
[Link]()
return Response([Link],
status=status.HTTP_201_CREATED)
return Response([Link],
status=status.HTTP_400_BAD_REQUEST)

URL mapping:

from [Link] import path


from .views import StudentAPIView

urlpatterns = [
path('students/', StudentAPIView.as_view()),
]

5️⃣ How it works


1. GET /students/ → Returns all students as JSON
2. POST /students/ → Creates a new student from JSON payload

Request example:
{
"name": "John Doe",
"age": 22
}

Response example (201 Created):

{
"id": 1,
"name": "John Doe",
"age": 22
}

6️⃣ When to use APIView

Use APIView when you need full control over the request/response handling.
If you want custom logic for GET/POST/PUT/PATCH/DELETE that doesn’t fit DRF’s
generic views, use APIView .

Tip: If your view is mostly CRUD for a model, use GenericAPIView + mixins or ViewSets
to avoid repeating boilerplate code.

If you want, I can make a diagram showing APIView vs GenericAPIView vs ViewSet, so


you can clearly see how DRF views hierarchy works.

Do you want me to make that diagram?

Perfect! Let’s go deep dive into DRF ViewSets, which are a powerful way to combine
multiple API actions into a single class. I’ll explain all the ones you mentioned with
examples.

VIEWSETS (DRF)
ViewSets allow you to group multiple related views (list, create, retrieve, update, delete)
into a single class.

Usually used with routers, which automatically generate URLs for each action.
DRF provides several types of viewsets for different use cases.
1️⃣ ViewSet
Purpose: Base viewset class.
You define your own actions (list, create, retrieve, update, destroy).
Does not automatically provide any CRUD methods; you need to define them
yourself.

Example:

from rest_framework import viewsets


from rest_framework.response import Response
from .models import Student
from .serializers import StudentSerializer

class StudentViewSet([Link]):

def list(self, request):


students = [Link]()
serializer = StudentSerializer(students, many=True)
return Response([Link])

def retrieve(self, request, pk=None):


student = [Link](pk=pk)
serializer = StudentSerializer(student)
return Response([Link])

Router URL mapping:

from rest_framework.routers import DefaultRouter


from .views import StudentViewSet

router = DefaultRouter()
[Link](r'students', StudentViewSet, basename='student')
urlpatterns = [Link]

GET /students/ → list


GET /students/1/ → retrieve

2️⃣ ViewSetMixin
Purpose: Provides common viewset behaviors like get_object() and
get_queryset() .
Typically combined with GenericAPIView to create GenericViewSet.
Key points:

Doesn’t provide HTTP methods by itself


Used internally to combine mixins + GenericAPIView for ViewSets

Example:

from rest_framework.viewsets import ViewSetMixin


from rest_framework.generics import GenericAPIView
from rest_framework import mixins
from .models import Student
from .serializers import StudentSerializer

class StudentListCreateView(ViewSetMixin,
[Link],
[Link],
GenericAPIView):
queryset = [Link]()
serializer_class = StudentSerializer

# GET → list, POST → create automatically via mixins

3️⃣ GenericViewSet
Purpose: Combines ViewSetMixin + GenericAPIView.
Base class for most model-based viewsets ( ModelViewSet ,
ReadOnlyModelViewSet ).
Allows using mixins to add only the actions you need.

Example:

from rest_framework.viewsets import GenericViewSet


from rest_framework import mixins
from .models import Student
from .serializers import StudentSerializer

class StudentGenericViewSet([Link],
[Link],
GenericViewSet):
queryset = [Link]()
serializer_class = StudentSerializer

GET /students/ → list


POST /students/ → create
4️⃣ ModelViewSet
Purpose: Full CRUD viewset for a model
Inherits from GenericViewSet + all CRUD mixins
Automatically provides: list , create , retrieve , update , partial_update ,
destroy

Example:

from rest_framework.viewsets import ModelViewSet


from .models import Student
from .serializers import StudentSerializer

class StudentModelViewSet(ModelViewSet):
queryset = [Link]()
serializer_class = StudentSerializer

GET /students/ → list


GET /students/1/ → retrieve
POST /students/ → create
PUT/PATCH /students/1/ → update
DELETE /students/1/ → delete

✅ Use ModelViewSet for most standard CRUD APIs.

5️⃣ ReadOnlyModelViewSet
Purpose: Like ModelViewSet but read-only
Only provides list and retrieve
Inherits from GenericViewSet + ListModelMixin + RetrieveModelMixin

Example:

from rest_framework.viewsets import ReadOnlyModelViewSet


from .models import Student
from .serializers import StudentSerializer

class StudentReadOnlyViewSet(ReadOnlyModelViewSet):
queryset = [Link]()
serializer_class = StudentSerializer

GET /students/ → list


GET /students/1/ → retrieve
POST/PUT/PATCH/DELETE → not allowed

✅ Use for APIs where clients should only read data.

Summary Table

ViewSet Purpose Provided Mixins Used


Actions
ViewSet Base None by ViewSetMixin
viewset default
ViewSetMixin Adds None -
common
methods
for
viewsets
GenericViewSet Base for Only if ViewSetMixin + GenericAPIView
model combined
viewsets with
mixins
ModelViewSet Full list, GenericViewSet +
CRUD create, List/Create/Retrieve/Update/Destroy
retrieve, mixins
update,
destroy
ReadOnlyModelViewSet Read- list, GenericViewSet + List/Retrieve
only retrieve mixins

💡 Tip:
Use ViewSet: when you want full control and write all methods manually
Use GenericViewSet: when you want partial CRUD using mixins
Use ModelViewSet: for full CRUD automatically
Use ReadOnlyModelViewSet: for read-only APIs

If you want, I can make a diagram showing all ViewSets hierarchy (ViewSet →
GenericViewSet → ModelViewSet / ReadOnlyModelViewSet) with mixins, which makes it
super easy to memorize.
Do you want me to make that diagram?

Ah! Perfect question — this is key for interviews and real projects. Let’s break it clearly:
when to use which DRF view/viewset or generic view/mixin/pagination/serializer, so it’s
easy to decide. I’ll structure it by category.

1️⃣ DRF Views


View Type When to Use Example
APIView You need full control over Custom
request/response, or endpoint that
custom behavior that calls multiple
doesn’t fit generic views. models, custom
validation, or
special HTTP
logic.
GenericAPIView + Mixins When you want partial Endpoint that
CRUD but don’t want to write only supports
boilerplate GET+POST, but
GET/POST/PUT/DELETE no DELETE.
methods.
Generic Views (ListAPIView, When you want standard Standard
CreateAPIView, CRUD functionality for a RESTful API for
RetrieveUpdateDestroyAPIView, single model, with minimal Student
etc.) code. model: list,
create, retrieve,
update, delete.

Rule of thumb:

If it’s mostly standard CRUD → use generic views


If you need custom logic → use APIView

2️⃣ DRF ViewSets


ViewSet When to Use Example
ViewSet When you want full Complex endpoint: list +
manual control over retrieve + extra actions like
actions but want to group /students/1/grades/ .
all endpoints in one class.
ViewSet When to Use Example
GenericViewSet + When you want partial Only list + create, or only
Mixins CRUD (list+create or retrieve + delete.
retrieve+update) without
writing full methods.
ModelViewSet Full CRUD for a single Standard REST API:
model with minimal code. /students/ → list, create,
retrieve, update, delete.
ReadOnlyModelViewSet When API is read-only. Public API for students: list
and detail, no modifications
allowed.

Rule of thumb:

Single model CRUD → ModelViewSet


Partial CRUD → GenericViewSet + mixins
Custom logic → ViewSet
Read-only → ReadOnlyModelViewSet

3️⃣ DRF Mixins


Mixin When to Use
CreateModelMixin Only POST endpoint
ListModelMixin Only GET list
RetrieveModelMixin Only GET detail
UpdateModelMixin Only PUT/PATCH
DestroyModelMixin Only DELETE

Rule of thumb: Combine mixins + GenericViewSet if you want custom combinations


without writing methods manually.

4️⃣ DRF Serializers


Serializer When to Use
Serializer Custom objects or complex validation logic not tied to
a model.
Serializer When to Use
ModelSerializer Standard model APIs → automatic fields +
create/update.
HyperlinkedModelSerializer RESTful APIs where related objects should be links
instead of IDs.
ListSerializer Bulk operations ( many=True ) or customizing lists.
BaseSerializer Full control over serialization/deserialization →
advanced use cases.

Rule of thumb:

Use ModelSerializer in most model-based APIs.


Use Serializer/BaseSerializer only if you need custom behavior.
HyperlinkedModelSerializer if API is hypermedia-driven.

5️⃣ DRF Pagination


Pagination When to Use
PageNumberPagination Standard pagination, simple apps.
LimitOffsetPagination Let client control number of items ( limit ) and starting point
( offset ).
CursorPagination Large datasets or frequently changing data → avoids
duplicates/missing items.
BasePagination Custom pagination logic (rarely used).

Rule of thumb:

Small apps → PageNumberPagination


Client-controlled → LimitOffsetPagination
Large or real-time data → CursorPagination

Quick “Decision Map”


1. Model CRUD API → ModelViewSet + ModelSerializer + Pagination
2. Read-only API → ReadOnlyModelViewSet
3. Partial CRUD API → GenericViewSet + mixins
4. Custom endpoint logic → APIView + Serializer
5. Bulk operations → ListSerializer or many=True in ModelSerializer
6. Simple pagination → PageNumberPagination, etc.

💡 Extra Tip:
Use ViewSets + routers whenever possible → less boilerplate.
Use GenericAPIView + Mixins for partial CRUD without routers.
Use APIView only if you need custom behavior that cannot be handled by generic
views or viewsets.

If you want, I can make a single visual diagram showing “Which DRF class to use
when”, including views, viewsets, serializers, pagination, so you can memorize it in 5
seconds.

Do you want me to make that diagram?

You might also like