The introduction

This article provides a brief analysis and summary of MIXins in DRF. Mixins are mainly used together with viewsets in DRF to associate HTTP methods with mixins related classes and methods. You can see my other blog post about viewsets, but I don’t want to tell you much about them.

from rest_framework import viewsets
Copy the code

In this viewset, as long as there are five Minxin classes, they correspond to HTTP methods as follows:

1. CreateModelMixin

# source
class CreateModelMixin(object):
    """Create a model instance ==> Create an instance"""
    def create(self, request, *args, **kwargs):
    
	Obtain serializer
        serializer = self.get_serializer(data=request.data)
        
        Verify serializer
        # raise_exception=True, if the validation fails, no further execution, directly raise an exception
        serializer.is_valid(raise_exception=True)
        
        Call the perform_create() method to save the instance
        self.perform_create(serializer)
        
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
    # save instance
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}
Copy the code

Suppose we now have a course model that maintains a number to record the number of course favorites, and a model in which users bookmark userfav (there should be a foreign key pointing to course). When a user bookmarks a course, In theory, now the post should be the instance of userfav, and obviously we need to add +1 to the bookmark of the corresponding course. At this point, we need to override the perform_create() method!

def perform_create(self, serializer):
Rewrite the logic for save
	instance = serializer.save()
	course = instance.course
	course.fav_num += 1
	course.save()

Copy the code

Obviously, this is not the only solution, we can also set it in Seriliazer, we can also use the DRF semaphores to solve this problem!

2. ListModelMixin

# source
class ListModelMixin(object):
    """List a querySet.==>"""
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        
        # This is a pagination function that works if pagination_class is set in viewSet
        Get the querySet for the current page, or None if there is no paging
        page = self.paginate_queryset(queryset)
        
        if page is not None:
	    Response(serializer.data)
	    The response also needs to serialize the relevant page information
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
Copy the code

ListModelMixin is generally used to fetch list pages, and in most cases is simple and does not require overriding the associated methods.

3. RetrieveModelMixin

# source
class RetrieveModelMixin(object):
    """Retrieve a model instance.==> Retrieve specific information about an object."""
    def retrieve(self, request, *args, **kwargs):
    	/obj/id/
    	# get_object() retrieves an object with this id
    	# Notice that setting lookup_field in viewSet gets the override get_object() method to specify what the object id is.
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)
Copy the code

There is a high probability of rewriting the Retrieve method, for example, when we are increasing the number of clicks, we often have to rewrite it.

4. RetrieveModelMixin

# source
class UpdateModelMixin(object):
    """Update a model instance.==> Update the contents of a specific object"""
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)
Copy the code

The implementation logic of RetrieveModelMixin basically integrates Create and Retrieve, gets a concrete instance, verifies it and saves it, and if you need to customize the update logic, you need to override the perform_update() method, Rewrite update() as little as possible

5. DestroyModelMixin

# source
class DestroyModelMixin(object):
    """ Destroy a model instance. """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()
Copy the code

The logic behind DestroyModelMixin is also relatively simple. Let’s take the following example of CreateModelMixin. When we unfavorites, our DestroyModelMixin will come into play. In the same way

def perform_create(self, serializer):
	instance = serializer.save()
	course = instance.course
	if course.fav_num > 0:
		course.fav_num -= 1
	else:
		course.fav_num = 0
	course.save()
Copy the code

summary

Mixins are relatively easy to understand. This article will briefly analyze the source code and the logic of each mixins. The most important thing is to learn how to rewrite their methods. In general, when we operate on one model and modify the data in another model, we need to rewrite the method of executing the save logic in this mixins.

CSDN:http://blog.csdn.net/l_vip/article/details/79142105