Classy Django REST Framework (DRF)
Classy Django REST Framework (DRF)
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. Views
APIView
Generic views ( ListAPIView , RetrieveAPIView , etc.)
ViewSets ( ModelViewSet , ReadOnlyModelViewSet )
2. Serializers
Serializer
ModelSerializer
HyperlinkedModelSerializer
3. Mixins
CreateModelMixin , ListModelMixin , etc.
Key attributes:
Key methods:
Example:
class HelloView(APIView):
def get(self, request):
return Response({"message": "Hello, World!"},
status=status.HTTP_200_OK)
These are DRF views that combine APIView + Mixins, so you don’t need to implement
standard CRUD operations manually.
Examples:
Key attributes:
queryset → Default queryset for the view
serializer_class → Serializer class
lookup_field → Default: 'pk' , field for retrieving single objects
Key methods:
Example:
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:
Key attributes:
Key methods:
Example:
class StudentViewSet([Link]):
queryset = [Link]()
serializer_class = StudentSerializer
3.1 Serializer
Key attributes:
Key methods:
Example:
class StudentSerializer([Link]):
id = [Link](read_only=True)
name = [Link](max_length=100)
age = [Link]()
def create(self, validated_data):
return [Link](**validated_data)
3.2 ModelSerializer
Key attributes:
Example:
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
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.
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:
Key methods:
Example:
class StudentGenericView(GenericAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
2️⃣ CreateAPIView
Purpose: Only supports POST requests (create new object)
Mixins used: CreateModelMixin + GenericAPIView
Key methods:
Example:
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:
Example:
class StudentDeleteView(DestroyAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
4️⃣ ListAPIView
Purpose: Only supports GET for listing objects
Mixins used: ListModelMixin + GenericAPIView
Key methods:
Example:
5️⃣ ListCreateAPIView
Purpose: Supports GET (list) + POST (create)
Mixins used: ListModelMixin + CreateModelMixin + GenericAPIView
Example:
class StudentListCreateView(ListCreateAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
Usage:
6️⃣ RetrieveAPIView
Purpose: Only supports GET for single object detail
Mixins used: RetrieveModelMixin + GenericAPIView
Key methods:
Example:
class StudentDetailView(RetrieveAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
7️⃣ RetrieveDestroyAPIView
Purpose: Supports GET (retrieve) + DELETE (destroy)
Mixins used: RetrieveModelMixin + DestroyModelMixin + GenericAPIView
Example:
class StudentRetrieveDestroyView(RetrieveDestroyAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
Usage:
8️⃣ RetrieveUpdateAPIView
Purpose: Supports GET + PUT/PATCH (update)
Mixins used: RetrieveModelMixin + UpdateModelMixin + GenericAPIView
Example:
class StudentRetrieveUpdateView(RetrieveUpdateAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
Usage:
9️⃣ RetrieveUpdateDestroyAPIView
Purpose: Supports GET + PUT/PATCH + DELETE
Mixins used: RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin +
GenericAPIView
Example:
class StudentRetrieveUpdateDestroyView(RetrieveUpdateDestroyAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
10️⃣ UpdateAPIView
Purpose: Only supports PUT/PATCH (update object)
Mixins used: UpdateModelMixin + GenericAPIView
Example:
class StudentUpdateView(UpdateAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
✅ 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.
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:
2️⃣ DestroyModelMixin
Purpose: Adds delete functionality (usually DELETE)
Typically used with GenericAPIView
Key methods:
Example:
Key methods:
Example:
4️⃣ RetrieveModelMixin
Purpose: Adds retrieve functionality (GET single object)
Key methods:
Example:
Key methods:
Example:
Usage:
💡 Tip:
All DRF generic views ( ListAPIView , CreateAPIView ,
RetrieveUpdateDestroyAPIView , etc.) are basically pre-built combinations of these
mixins + GenericAPIView.
For example:
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.
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 .
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]
Usage in view:
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:
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
3️⃣ LimitOffsetPagination
Purpose: Pagination using limit and offset query params
URL example: /students/?limit=5&offset=10
Key attributes:
Example:
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:
Example:
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
✅ 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.
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.
Key attributes:
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:
class StudentSerializer([Link]):
id = [Link](read_only=True)
name = [Link](max_length=100)
age = [Link]()
2️⃣ ModelSerializer
Purpose: Shortcut for serializers tied to Django models.
Automatically generates fields and create() / update() methods from the model.
Key attributes:
Example:
3️⃣ HyperlinkedModelSerializer
Purpose: Like ModelSerializer , but represents relationships with URLs instead of
primary keys.
Useful for RESTful APIs with hyperlinks.
Key attributes:
Example:
class
StudentHyperlinkedSerializer([Link]):
class Meta:
model = Student
fields = ['url', 'id', 'name', 'age']
extra_kwargs = {
'url': {'view_name': 'student-detail', 'lookup_field': 'pk'}
}
{
"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:
Example:
class StudentSerializer([Link]):
class Meta:
model = Student
fields = ['id', 'name', 'age']
class StudentListSerializer([Link]):
child = StudentSerializer()
Usage:
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:
class MyBaseStudentSerializer(BaseSerializer):
def to_representation(self, instance):
return {
'id': [Link],
'name': [Link](), # example of custom formatting
'age': [Link]
}
✅ Use BaseSerializer when you want full control over input/output without automatic
field mapping.
💡 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.
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 ?
Key points:
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.)
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
# [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):
URL mapping:
urlpatterns = [
path('students/', StudentAPIView.as_view()),
]
Request example:
{
"name": "John Doe",
"age": 22
}
{
"id": 1,
"name": "John Doe",
"age": 22
}
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.
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:
class StudentViewSet([Link]):
router = DefaultRouter()
[Link](r'students', StudentViewSet, basename='student')
urlpatterns = [Link]
2️⃣ ViewSetMixin
Purpose: Provides common viewset behaviors like get_object() and
get_queryset() .
Typically combined with GenericAPIView to create GenericViewSet.
Key points:
Example:
class StudentListCreateView(ViewSetMixin,
[Link],
[Link],
GenericAPIView):
queryset = [Link]()
serializer_class = StudentSerializer
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:
class StudentGenericViewSet([Link],
[Link],
GenericViewSet):
queryset = [Link]()
serializer_class = StudentSerializer
Example:
class StudentModelViewSet(ModelViewSet):
queryset = [Link]()
serializer_class = StudentSerializer
5️⃣ ReadOnlyModelViewSet
Purpose: Like ModelViewSet but read-only
Only provides list and retrieve
Inherits from GenericViewSet + ListModelMixin + RetrieveModelMixin
Example:
class StudentReadOnlyViewSet(ReadOnlyModelViewSet):
queryset = [Link]()
serializer_class = StudentSerializer
Summary Table
💡 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.
Rule of thumb:
Rule of thumb:
Rule of thumb:
Rule of thumb:
💡 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.