Django Rest Framework Note for Beginners
Django Rest Framework Note for Beginners
Django REST Framework (DRF) is a powerful toolkit for building Web APIs in Django. It simplifies the
process of creating RESTful APIs by offering a flexible and modular architecture.
Key Features:
Serialization: DRF helps in converting Django models to JSON or other content types and vice versa .
View sets and Routers: DRF provides View Sets to reduce repetitive code for CRUD operations and
Routers to automatically generate URL routes.
Throttling, Permissions, and Filtering: DRF offers tools to manage rate-limiting, access control, and
filtering of query results.
Serialization
Serialization in Django REST Framework (DRF) refers to the process of converting complex data types,
like Django models or querysets, into native Python data types that can then be easily rendered into
JSON, XML, or other content types.
2. Deserialization: Converts JSON or input data into Python objects, allowing you to validate the data
and save it back to the database.
1. ModelSerializer
This type of serializer is used when you want to automatically generate fields for a Django model. It
provides an easy way to create serializers without manually defining each field.
Basic Syntax:
You can also specify the fields you want, e.g., fields = ['name', 'description'].
class MyManualSerializer(serializers.Serializer):
name = serializers.CharField(max_length=100)
description = serializers.CharField()
price = serializers.DecimalField(max_digits=10, decimal_places=2)
return MyModel.objects.create(**validated_data)
return instance
This is useful when you have more complex validation or custom data transformations that aren't easily
handled by ModelSerializer.
3. HyperlinkedModelSerializer
The HyperlinkedModelSerializer is similar to the ModelSerializer, but instead of using a primary key to
represent relationships, it uses hyperlinks (URLs). This is helpful when you are working with RESTful APIs
where resources are often identified via URLs.
Basic Syntax:
class Meta:
model = MyModel
fields = ['url', 'name', 'description']
The url field is automatically included by DRF to provide hyperlinks for the object’s details.
4. ListSerializer
The ListSerializer is useful for serializing multiple objects at once. By default, DRF handles lists of objects
using ListSerializer, but you can customize it when you want to perform bulk updates or other batch
operations.
Basic Syntax:
class MyChildSerializer(serializers.Serializer):
name = serializers.CharField()
class MyListSerializer(serializers.ListSerializer):
child = MyChildSerializer()
class MyModelSerializer(serializers.ModelSerializer):
custom_field = serializers.SerializerMethodField()
class Meta:
model = MyModel
fields = ['name', 'description', 'custom_field']
SerializerMethodField: A read-only field that gets its value by calling a method on the serializer
class.
1. CharField
# Description: A field for character input.
2. **IntegerField**
- **Description**: A field for integer input.
3. **BooleanField**
- **Description**: A field that accepts a boolean value (True or False).
4. **EmailField**
- **Description**: A field for email addresses.
5. **DateField**
- **Description**: A field for date input.
6. **DecimalField**
- **Description**: A field for decimal numbers.
7. **FloatField**
- **Description**: A field for floating-point numbers.
8. **ListField**
- **Description**: A field that accepts a list of items.
9. **URLField**
- **Description**: A field for URLs.
2. allow_blank: Applicable for fields like CharField. When set to True, the field can be blank even if it is
required.
4. validators: A list of custom validation functions that can be applied to the field data.
5. help_text: A string that provides additional information about the field. This can be used for API
documentation.
6. error_messages: A dictionary that allows customization of error messages for various validation
errors.
Deserialization
Deserialization in Django REST Framework (DRF) is the process of converting incoming data (usually in
JSON format) into complex types such as Django model instances or Python objects. This process
includes validating the data to ensure it meets the required criteria before it can be saved or processed.
2. Create a Serializer Instance: A serializer instance is created using the incoming data.
3. Validate the Data: The serializer validates the data against the defined rules (such as required fields,
field types, etc.).
4. Save the Data: If the data is valid, you can save it to the database or perform any other necessary
operations.
# models.py
class User(models.Model):
username = models.CharField(max_length=150)
email = models.EmailField()
age = models.IntegerField(null=True, blank=True)
# serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email', 'age']
class UserCreateView(APIView):
save(): If the data is valid, calling this method will create or update the model instance based on the
validated data. It can also accept additional keyword arguments to customize the save operation.
create() and update(): If you override these methods in your serializer, you can customize how
instances are created or updated during the deserialization process.
if serializer.is_valid():
# Save the data
else:
Validation
Validation in Django Rest Framework (DRF) is an essential feature that ensures the integrity and
correctness of data being processed in your API. It can occur during serialization (when converting data
to and from complex types) and helps prevent invalid data from being saved to the database.
3. Built-in Validators: DRF provides several built-in validators for common scenarios, like checking
uniqueness, required fields, or value ranges.
Examples of Validation
1. Field-Level Validation
You can create custom validation for specific fields in your serializer.
Example:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'author', 'published_date']
2. Object-Level Validation
You can validate the entire object by overriding the validate method. This is useful for validating
relationships between fields or cross-field dependencies.
Example:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'author', 'published_date']
class BookSerializer(serializers.ModelSerializer):
title = serializers.CharField(validators=[MinLengthValidator(5)]) # Min len
gth of 5
class Meta:
model = Book
fields = ['title', 'author', 'published_date']
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['title', 'author', 'published_date']
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Views In DRF
In Django REST Framework (DRF), views are responsible for handling HTTP requests and returning
responses. DRF provides two main types of views for handling HTTP requests: APIView and ViewSet.
API view is the core mechanism used to handle HTTP requests and return HTTP responses, typically in
the form of JSON data. There are two primary ways to create API views in DRF:
1. Function-Based Views (FBVs): These are simple Python functions that handle HTTP requests.
2. Class-Based Views (CBVs): These are Python classes that handle HTTP requests. DRF provides
several types of class-based views, such as APIView and ViewSet.
Basic Syntax:
Here’s a basic example of using FBVs in DRF to create an API for listing and creating providers:
@api_view(['GET', 'POST'])
def provider_list(request):
if request.method == 'GET':
providers = Provider.objects.all()
serializer = ProviderSerializer(providers, many=True)
return Response(serializer.data)
Explanation:
@api_view(['GET', 'POST']): This decorator tells DRF that this view can handle GET and POST
requests.
If it’s a POST request, it validates the incoming data and saves a new provider.
Basic Syntax:
Here’s a basic example of using CBVs with APIView:
class ProviderList(APIView):
Explanation:
The class ProviderList inherits from APIView.
The get method handles GET requests, retrieving and serializing the providers.
The post method handles POST requests, validating the data and saving a new provider if valid.
urlpatterns = [
# For FBV
# For CBV
GenericAPIView: The base class for all generic views, which provides basic functionality.
ModelViewSet: Combines all of the above to provide a full set of CRUD operations.
Basic Syntax
Using a generic view typically involves the following steps:
1. Define a class that inherits from a DRF generic view (e.g., ListAPIView, CreateAPIView, etc.).
# models.py
class Provider(models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
email = models.EmailField()
def __str__(self):
return self.name
# serializers.py
class Meta:
model = Provider
fields = '__all__' # Or specify fields: ['id', 'name', 'age', 'email']
# views.py
class ProviderListCreateView(ListCreateAPIView):
queryset = Provider.objects.all()
serializer_class = ProviderSerializer
class ProviderRetrieveUpdateDestroyView(RetrieveUpdateDestroyAPIView):
queryset = Provider.objects.all()
serializer_class = ProviderSerializer
# urls.py
urlpatterns = [
path('providers/', ProviderListCreateView.as_view(), name='provider-list-creat
e'),
path('providers/<int:pk>/', ProviderRetrieveUpdateDestroyView.as_view(), name='p
rovider-detail'),
Explanation
1. ListCreateAPIView: This view handles both GET (to list all providers) and POST (to create a new
provider) requests. You only need to define the queryset and serializer_class, and DRF will take
care of the rest.
2. RetrieveUpdateDestroyAPIView: This view handles GET, PUT, PATCH, and DELETE requests for a
single provider specified by its primary key (pk). It also requires just the queryset and
serializer_class.
Consistency: Generic views ensure consistent behavior across your API endpoints.
Flexibility: You can still override methods for custom behavior while benefiting from the built-in
functionality.
Generic API views are a powerful way to quickly implement common patterns for API endpoints such
as listing, creating, updating, and deleting objects. These views come with several attributes that you
can configure or override to customize their behavior.
Here’s a brief explanation of the key attributes of GenericAPIView, which is the base class for all generic
views in DRF.
queryset
Purpose: The queryset attribute defines the set of objects that the view will operate on. This is used
to retrieve data from the database.
queryset = Provider.objects.all()
serializer_class
serializer_class = ProviderSerializer
lookup_field
Purpose: Defines the field that will be used to look up an object by its identifier. By default, this is pk
(primary key), but you can customize it if needed (e.g., using a slug or another field).
lookup_field = 'id'
lookup_url_kwarg
Purpose: Defines the URL keyword argument that will be used to look up the object. If
lookup_url_kwarg is not set, it defaults to the value of lookup_field.
lookup_url_kwarg = 'provider_id'
1. filter_backends
Purpose: This is a list of filter backends used to filter the queryset. For example, you can use it to
apply ordering, search, or custom filtering.
pagination_class
Purpose: Defines the pagination class used for paginating the queryset. You can set this to a
custom pagination class or use DRF’s built-in paginators.
permission_classes
Purpose: Defines the permission classes that control who can access the view. This is a list of
permission classes (e.g., IsAuthenticated, AllowAny, etc.).
authentication_classes
throttle_classes
Purpose: This is a list of throttle classes that apply throttling to limit the rate of requests to your API.
get_queryset()
Purpose: While the queryset attribute defines a static queryset, you can override get_queryset() to
dynamically generate a queryset, based on request parameters or custom logic.
def get_queryset(self):
return Provider.objects.filter(is_active=True)
get_serializer_class()
Purpose: Allows you to dynamically choose a different serializer class, based on certain conditions
like the request method or user type.
def get_serializer_class(self):
if self.request.method == 'GET':
return ProviderDetailSerializer
return ProviderSerializer
get_object()
Purpose: This method is used to retrieve a specific object, and you can override it if you need
custom lookup behavior beyond the default lookup_field.
def get_object(self):
obj = get_object_or_404(Provider, id=self.kwargs['provider_id'])
return obj
get_serializer_context()
Purpose: This method allows you to pass additional context data to the serializer, such as the
current user or other request-specific information.
Mixins
In Django REST Framework (DRF), mixins are reusable blocks of behavior that allow you to add specific
functionality to views, such as creating, updating, deleting, or listing objects. Mixins help you build
custom views without having to inherit from the more complex generic views, providing fine-grained
control over your API endpoints.
1. CreateModelMixin: Provides the ability to create a new object (handles HTTP POST requests).
2. ListModelMixin: Provides the ability to list a queryset of objects (handles HTTP GET requests).
3. RetrieveModelMixin: Provides the ability to retrieve a single object (handles HTTP GET requests with
an object id).
4. UpdateModelMixin: Provides the ability to update an existing object (handles HTTP PUT and PATCH
requests).
5. DestroyModelMixin: Provides the ability to delete an object (handles HTTP DELETE requests).
# models.py
def __str__(self):
return self.name
#serializers.py
class Meta:
model = Provider
fields = '__all__'
We’ll implement a basic CRUD interface for the Provider model using mixins.
# views.py
# urls.py
urlpatterns = [
Used in combination with GenericAPIView to provide the ability to list multiple objects (via a
GET request).
Provides a list() method, which you call inside the get() method of your view.
2. CreateModelMixin
Used to add the ability to create a new object (via a POST request).
Provides a create() method, which you call inside the post() method of your view.
3. RetrieveModelMixin
Provides a retrieve() method, which you call inside the get() method of your view.
4. UpdateModelMixin
Provides two methods: update() for full updates (PUT) and partial_update() for partial updates
(PATCH).
5. DestroyModelMixin
Provides a destroy() method, which you call inside the delete() method of your view.
Simplicity: By using mixins, you avoid duplicating logic for common tasks like listing, retrieving,
updating, or deleting objects.
Customization: Mixins give you the flexibility to override individual methods and add custom behavior
while keeping your views concise.
3. RetrieveAPIView: For retrieving a single object (GET request with an object id).
6. ListCreateAPIView: For listing objects and creating new ones (GET and POST requests).
7. RetrieveUpdateAPIView: For retrieving and updating a single object (GET, PUT, PATCH requests).
8. RetrieveDestroyAPIView: For retrieving and deleting a single object (GET, DELETE requests).
These concrete classes are built on top of GenericAPIView and the appropriate mixins, meaning they
simplify CRUD operations significantly.
# models.py
def __str__(self):
return self.title
# serializers.py
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = '__all__'
f
Step 2: Using Concrete View Classes in Views
# views.py
class TaskListView(ListAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
class TaskCreateView(CreateAPIView):
queryset = Task.objects.all()
serializer_class = TaskSerializer
# views.py
# views.py
# views.py
# views.py
# urls.py
urlpatterns = [
ViewSets
In Django REST Framework (DRF), ViewSets are a higher-level abstraction over views that allow you to
combine the logic for handling multiple types of requests (like list, create, retrieve, update, and delete)
in a single class. Instead of defining individual views for each action (as with GenericAPIView), you can
define a single ViewSet that handles the common CRUD actions in one place.
2. ModelViewSet: A viewset that provides default implementations for the standard actions (list,
create, retrieve, update, partial_update, and destroy).
# models.py
def __str__(self):
return self.title
# serializers.py
class Meta:
model = Task
fields = '__all__'
# views.py
# urls.py
router = DefaultRouter()
You don't need to manually specify each action in the urls.py file. The router handles this for you.
A base class that provides the building blocks for creating custom actions. It doesn't provide
any pre-built functionality for CRUD operations.
class CustomViewSet(viewsets.ViewSet):
def list(self, request):
# Custom logic for listing objects
pass
ModelViewSet:
Extends ViewSet and automatically provides CRUD operations (list, create, retrieve, update, destroy).
ReadOnlyModelViewSet:
A read-only version of ModelViewSet that provides only the list and retrieve actions.
Useful for situations where you want to expose data for reading but not allow modifications.
class TaskReadOnlyViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Task.objects.all()
serializer_class = TaskSerializer
Basic Authentication
Token Authentication
Custom Authentication
Each method has its own use case depending on the type of API and how you want to manage security.
1. Session Authentication
This method uses Django's session framework to authenticate users. It is typically used for browser-
based, HTML-rendered views and is the default authentication method in Django. This is most suitable
for APIs consumed by web clients that are also using Django sessions.
Example:
A user logs into your Django website.
The API checks the session ID in the browser cookies for the user.
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
This method is not ideal for APIs consumed by non-browser clients (e.g., mobile apps) because sessions
rely on cookies.
2. Basic Authentication
This method uses a simple HTTP authentication scheme where the username and password are sent in
the HTTP header (Base64 encoded). It is easy to set up but not secure, as credentials are sent in each
request and need to be transmitted over HTTPS.
To enable Basic Authentication in DRF:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
This method is mainly useful for testing but not recommended for production since credentials are
exposed unless you use HTTPS.
3. Token Authentication
In this method, each user is assigned a token that is used to authenticate API requests. The token is sent
in the headers with each request instead of a username and password.
Example:
A user logs in and receives a token.
The user sends the token with every API request in the Authorization header.
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
user = User.objects.get(username='your_username')
token = Token.objects.create(user=user)
print(token.key)
Now you can use this token in the Authorization header for all requests.
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
# urls.py
TokenRefreshView,
urlpatterns = [
To obtain a token, send a POST request with your username and password:
curl -X POST "http://example.com/api/token/" \
H "Content-Type: application/json"
5. Custom Authentication
If you have specific authentication needs (e.g., custom token mechanisms), you can implement your
own custom authentication by subclassing BaseAuthentication.
# custom_auth.py
class CustomTokenAuthentication(BaseAuthentication):
try:
user = User.objects.get(auth_token=token)
except User.DoesNotExist:
raise AuthenticationFailed('Invalid token')
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'path.to.custom_auth.CustomTokenAuthentication',
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
2. IsAuthenticated
3. IsAdminUser
4. IsAuthenticatedOrReadOnly
5. DjangoModelPermissions
6. DjangoModelPermissionsOrAnonReadOnly
7. Custom Permissions
1. AllowAny
This permission allows unrestricted access to the view or endpoint. Any user, whether authenticated or
not, can access the resource.
Example:
class MyPublicView(APIView):
permission_classes = [AllowAny]
Use AllowAny when you want to make certain views or endpoints publicly accessible.
2. IsAuthenticated
This permission restricts access to authenticated users only. If a user is not authenticated (i.e., they
are anonymous), access is denied.
Example:
If a user tries to access this view without being authenticated, they will receive a 401 Unauthorized
response.
3. IsAdminUser
This permission restricts access to users who are staff members (i.e., users with is_staff=True). Only
admin users can access the view.
Example:
class AdminOnlyView(APIView):
permission_classes = [IsAdminUser]
If a non-admin user tries to access this view, they will receive a 403 Forbidden response.
4. IsAuthenticatedOrReadOnly
This permission allows full access to authenticated users, but only read-only access (GET, HEAD,
OPTIONS) for unauthenticated users. This is useful for public APIs where users can read data without
logging in, but must authenticate to make changes.
Example:
class ReadOrEditView(APIView):
permission_classes = [IsAuthenticatedOrReadOnly]
Unauthenticated users will be restricted from performing write operations (POST, PUT, DELETE, etc.).
5. DjangoModelPermissions
class MyModelViewSet(ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
permission_classes = [DjangoModelPermissions]
In this case, users need to have the corresponding model-level permissions (add_mymodel,
change_mymodel, delete_mymodel) to perform each action.
6. DjangoModelPermissionsOrAnonReadOnly
This is a variation of DjangoModelPermissions. It grants read-only access to anonymous users while
applying model-level permissions for authenticated users.
Example:
class MyModelViewSet(ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
permission_classes = [DjangoModelPermissionsOrAnonReadOnly]
Unauthenticated users can view the data, but authenticated users need specific model permissions to
modify it.
7. Custom Permissions
DRF allows for custom permissions when you need more complex or specific logic for your views. A
custom permission class is a subclass of BasePermission and implements a has_permission or
has_object_permission method.
"""
class OwnerOnlyView(APIView):
permission_classes = [IsAuthenticated, IsOwner]
obj = MyModel.objects.get(pk=pk)
self.check_object_permissions(request, obj) # Important for object-level perm
ission check
return Response({"message": "You are the owner of this object!"})
This custom permission ensures that only the owner of the object can perform certain actions on it.
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
class MyView(APIView):
permission_classes = [IsAuthenticatedOrReadOnly]
class MyModelViewSet(ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
permission_classes = [IsAdminUser]
Combining Permissions
You can combine multiple permission classes. DRF will evaluate each one, and the user must satisfy all
of them to be granted access.
Example:
class AdminOnlyAuthenticatedView(APIView):
permission_classes = [IsAuthenticated, IsAdminUser]
In this example, the user must both be authenticated and an admin to access the
view.
Pagination
Pagination in Django REST Framework (DRF) is a way to divide large sets of data into smaller,
manageable parts, typically by displaying only a few records per page. Pagination allows APIs to return
data in chunks rather than all at once, which improves performance and usability, especially for APIs
that deal with large datasets.
CursorPagination: This style is suitable for large datasets and provides an opaque cursor to navigate
through the results.
LimitOffsetPagination: This style uses query parameters limit and offset to control pagination.
Configuration:
In
settings.py, define the pagination class globally
settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10, # Number of records per page
}
Example with View:
python
Copy code
from rest_framework.pagination import PageNumberPagination
from rest_framework.generics import ListAPIView
from myapp.models import MyModel
from myapp.serializers import MyModelSerializer
class MyModelListView(ListAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
pagination_class = PageNumberPagination # Optional, use if overriding global pa
gination
To access paginated results, the client can request different pages by using the page query parameter:
GET /api/mymodels/?page=2
2. LimitOffsetPagination
This pagination style allows the client to specify the number of results to return (limit) and an offset to
define where to start returning results.
Configuration:
In
settings.py, define the pagination class
settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 10, # Default number of records if no limit is provided
}
Example with View:
from rest_framework.pagination import LimitOffsetPagination
from rest_framework.generics import ListAPIView
from myapp.models import MyModel
from myapp.serializers import MyModelSerializer
GET /api/mymodels/?limit=10&offset=20
This will return 10 items starting from the 21st item (0-indexed).
CursorPagination
Cursor pagination is ideal for large datasets where ordering by an index is required. Instead of page
numbers or offsets, it uses a unique cursor (an opaque token) to mark the position of the next page.
Configuration:
In
settings.py, define the pagination class:
#settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
'PAGE_SIZE': 10,
}
Example with View
from rest_framework.pagination import CursorPagination
from rest_framework.generics import ListAPIView
from myapp.models import MyModel
from myapp.serializers import MyModelSerializer
class MyModelListView(ListAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
pagination_class = CursorPagination # Optional, use if overriding global pagina
tion
GET /api/mymodels/?cursor=abc123
The API provides a cursor in the response that can be used to retrieve the next set of results.
Custom Pagination
You can also create custom pagination classes by subclassing DRF's pagination classes.
class MyModelListView(ListAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
pagination_class = CustomPageNumberPagination
json
{
"count": 100, # Total number of records
"next": "http://api.example.com/mymodels/?page=3", # URL for the next page
"previous": "http://api.example.com/mymodels/?page=1", # URL for the previous p
age
"results": [
{
"id": 21,
"name": "Item 21",
"description": "Description for item 21"
},
...
]
}
The next and previous fields provide links to the next and previous pages, and t
he results field contains the paginated data.
Filter Classes
In Django REST Framework (DRF), filtering allows you to restrict the data returned by your API based on
certain conditions. DRF supports filtering using query parameters, and you can achieve this with the
django-filter package or DRF's built-in FilterBackend.
Django Filter: A powerful and flexible third-party package used to filter queryset data.
Example:
python
class MyModelListView(ListAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
def get_queryset(self):
queryset = super().get_queryset()
param = self.request.query_params.get('param', None) # Get 'param' from que
ry params
if param is not None:
queryset = queryset.filter(field=param) # Filter the queryset
return queryset
Here, you can filter by adding a query parameter in the URL like:
http
Copy code
GET /api/mymodels/?param=value
2. Using django-filter for More Advanced Filtering
django-filter is a robust package used for more complex filtering in DRF. It all
ows you to define custom filter logic using a FilterSet class.
Installation:
bash
Copy code
pip install django-filter
Add to settings.py:
python
Copy code
#settings.py
Define a FilterSet:
You define filter logic using a FilterSet class from django_filters.
Example:
class MyModelFilter(django_filters.FilterSet):
name = django_filters.CharFilter(field_name='name', lookup_expr='icontains') #
Filter by name (case insensitive)
min_age = django_filters.NumberFilter(field_name='age', lookup_expr='gte') #
Filter by minimum age
max_age = django_filters.NumberFilter(field_name='age', lookup_expr='lte') #
Filter by maximum age
class Meta:
model = MyModel
fields = ['name', 'min_age', 'max_age']
class MyModelListView(ListAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = MyModelFilter # Apply the custom filterset
To filter results, the client can pass query parameters like:
GET /api/mymodels/?name=john&min_age=20&max_age=50
Example:
4. OrderingFilter
OrderingFilter allows you to specify the order of the results based on certain fields.
class MyModelListView(ListAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
filter_backends = [SearchFilter]
search_fields = ['name', 'description'] # Fields to search in
To perform a search, the client uses the search query parameter:
http
GET /api/mymodels/?search=john
Example:
## from rest_framework.filters import OrderingFilter
from rest_framework.generics import ListAPIView
from myapp.models import MyModel
from myapp.serializers import MyModelSerializer
class MyModelListView(ListAPIView):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['name', 'age'] # Fields to order by
To order the results, the client can use the ordering query parameter:
http