SoFunction
Updated on 2025-03-02

Recording of process of DRF filtering sorting pagination exception handling

1. Filter

For list data to be filtered through fields, you need to add the django-filter module

How to use:

# 1. Register, register in the appINSTALLED_APPS = [
    'django_filters',
]

# 2. ConfigurationREST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    )
}

# 3. Add filter_fields attribute to the view and specify the filtered fieldsclass BooksView(ModelViewSet):
    queryset = ()
    serializer_class = BooksSerializer

    filter_fields = ('title',) # Which field can the configuration be filtered by    
# http://127.0.0.1:8000/books/?title=Dream of the Red Chamber

2. Sort

Sort can be quickly used by the OrderingFilter provided by Rest Framework to indicate that data is sorted by specified fields.

How to use:

# 1. First set filter_backends=[OrderingFilter] in the view# 2. Then add the ordering_fields property to the view to specify the sorting field
from rest_framework.filters import OrderingFilter
class BooksView(ModelViewSet):
    queryset = ()
    serializer_class = BooksSerializer

    filter_backends = [OrderingFilter] # Step 1    ordering_fields = ['price','id'] # Step 2    
# http://127.0.0.1:8000/books/?ordering=id Check whether there are specified sorted fields through ordering, and sort them through fields# -id means to sort in reverse order for id fields# id means ascending order for id fields

3. Pagination

First of all, Rest Framework provides three paging methods, and

  • PageNumberPagination
  • LimitOffsetPagination
  • CursorPagination

Usage method 1: You can directly inherit and use it, but the configuration parameters need to be configured inside

Usage method 2: inherit the parent class pager through subclasses, and directly modify the parameters of the parent class in the subclass (recommended)

PageNumberPagination

Properties in subclasses:

  • page_size: Number of pages per page
  • page_query_param: The number of pages sent by the front end, the default "page"
  • page_size_query_param: The front-end sends the keyword name for each page, default None
  • max_page_size: The maximum number of pages per page that the front-end can set at most

How to use:

from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination
from  import Books
from  import BooksSerializer

# Step 1:class BookPageNumberPagination(PageNumberPagination):
    page_size = 3         # Number of bars per page    page_query_param = 'page'   # Query the key on which page    page_size_query_param = 'size'  # Number of pieces displayed on each page    max_page_size = 5   # Maximum number of pieces per page

class BookView(ListAPIView):
    queryset = ()
    serializer_class = BooksSerializer
    
    # Step 2: Pagination configuration    pagination_class = BookPageNumberPagination
    
    
# url: http://127.0.0.1:8000/books/?page=1&size=5 Query page 1, displaying a total of five pieces of data

LimitOffsetPagination

Properties in subclasses:

  • default_limit: default limit, default value is consistent with PAGE_SIZE settings
  • limit_query_param: limit parameter name, default 'limit'
  • offset_query_param: offset parameter name, default 'offset'
  • max_limit: maximum limit limit, default None

How to use:

from rest_framework.generics import ListAPIView
from rest_framework.pagination import LimitOffsetPagination
from  import Books
from  import BooksSerializer

# Step 1:class BookLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 3           # Number of bars per page    limit_query_param = 'limit'     # Take a few more pieces in the future    offset_query_param = 'offset'   # From which one to how many benchmarks to take    max_limit = 5       # How many items can be obtained per page

class BookView(ListAPIView):
    queryset = ()
    serializer_class = BooksSerializer
    
    # Step 2: Pagination configuration    pagination_class = BookLimitOffsetPagination
    
    
# url: http://127.0.0.1:8000/books/?limit=3&offset=4 Get 4 pieces of data from the third item to the next

CursorPagination

Properties in subclasses:

  • cursor_query_param: default query field, no modification is required
  • page_size: Number of pages per page
  • Ordering: What sort is required to specify

How to use:

CursorPagination's query speed is fast, but it cannot be located to check this way. You either check forward or backward.

from rest_framework.generics import ListAPIView
from rest_framework.pagination import CursorPagination
from  import Books
from  import BooksSerializer

# Step 1:class BookCursorPagination(CursorPagination):
    cursor_query_param = 'cursor'   # Keys for querying per page    page_size = 3       # Number of pieces displayed per page    ordering = 'id'    # Sort fields

class BookView(ListAPIView):
    queryset = ()
    serializer_class = BooksSerializer
    
    # Step 2: Pagination configuration    pagination_class = BookCursorPagination
    
    
# url:http://127.0.0.1:8000/books/?cursor=cD0z

Inherit APIView usage method

If you use it like Method 1 and Method 2, you must inherit the ListAPIView and then configure it directly.

However, if the view class inherits GenericAPIView or APIView, another method is needed:

How to use:

# 1. Define a pagerclass BookPageNumberPagination(PageNumberPagination):
    page_size = 3         # Number of bars per page    page_query_param = 'page'   # Query the key on which page    page_size_query_param = 'size'  # Number of pieces displayed on each page    max_page_size = 5   # Maximum number of pieces per page

class BookView(APIView):

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

        # 2. Instantiate to get a pager object        page_obj = BookPageNumberPagination()
        
        # 3. Call paginate_queryset to return data on each page        book_list = page_obj.paginate_queryset(book_list, request, view=self)

        # 4. Get the previous page next page link        next_url = page_obj.get_next_link()
        previous_url = page_obj.get_previous_link()

        #5. Serialization        book_ser = BooksSerializer(book_list, many=True)
        
        # 6. Add to the response message        data = {'next_url': next_url, 'previous_url': previous_url, 'data': book_ser.data}
        return Response(data=data)

4. Exception handling

Exception handling is mainly used to unify interface return

Source code analysis

Exception handling in APIView has been configured

'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',

def exception_handler(exc, context):
    # First determine whether it is 404    if isinstance(exc, Http404): # Exc is an exception object with exception information        exc = ()
    # Then determine whether it is a permission issue    elif isinstance(exc, PermissionDenied):
        exc = ()  # For example, permission issues will return a dictionary        
 # Determine whether the API exceptions you throw -> Authentication permissions These are exceptions that inherit the API    if isinstance(exc, ):
        headers = {}
        if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
        if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % 

        if isinstance(, (list, dict)):
            data = 
        else:
            data = {'detail': }

        set_rollback()
        return Response(data, status=exc.status_code, headers=headers)
    # As long as the above exceptions are handled   

    return None  # It means that some exceptions are not processed, and they will be handed over to Django for handling themselves.

How to deal with it

Because some dir exceptions are not processed, and Django handles them not in line with our standards, we need to write a unified exception class to replace them and handle all situations. As long as the front-end exceptions appear, what you see is a fixed thing.

How to write:

Rewriting a class is basically the same as it. When configuring it, it is configured globally.

#  app01_auth.py
from rest_framework.views import exception_handler
from rest_framework.response import Response

def app01_exception_handler(exc, context):
    response = exception_handler(exc, context)  # We also need the original drf processing    # There are two cases, one is None, drf is not processed, Django handles, but the process does not meet the requirements    # response object, drf handles what we need

    if not response:
        # If not handled, then we handled it ourselves        return Response(data={'status': 400, 'error': str(exc)}, status=400)
    else:
        # drf has processed it, then take out the information it processes and reprocess it        return Response(data={'status': 400, 'error': ('detail')}, status=400)

Then configure the global configuration:

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'app01.app_auth.app01_exception_handler',
}

5. Encapsulate Response objects

class APIResponse(Response):
    def __init__(self,code=100,msg='success',data=None,status=None,headers=None,**kwargs):
        
        dic = {'code': code, 'msg': msg}
        
        if  data:
            dic = {'code': code, 'msg': msg,'data':data}
            
        (kwargs)
        
        super().__init__(data=dic, status=status,headers=headers)
        
        
# usereturn APIResponse(data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee')
return APIResponse(data={"name":'xiaoyang'})
return APIResponse(code='101',msg='mistake',data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee',header={})

Summarize

This is the end of this article about the exception handling of DRF filtering sorting pagination. For more related DRF filtering sorting pagination content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!