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