Now if you take a look at the way we get a product or create a product below
'''this is its CBV implementation'''class ProductList(APIView): def get(self, request): queryset = Product.objects.select_related('collection').all() serializer = ProductSerializer(queryset, many=True, context={'request': request}) return Response(serializer.data)
def post(self, request): serializer = ProductSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED)And you compare it to how we get and create a collection below
def collection_list(request): if request.method == 'GET': '''get all collections, and annotate them with the number of products in each collection''' queryset = Collection.objects.annotate(products_count=Count('products')).all() serializer = CollectionSerializer(queryset, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = CollectionSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED)You will notice that aside some 1 or 2 minor differences, they are all implemented with the same pattern. Now this is an advantage of Class Based Views - its reusability.
This is where mixins come into place, a mixin is a class that encapsulates the pattern of code like the ones above.
To use mixins you need to import them from ‘rest_framework.mixins’…you can import the ListModelMixin and CreateModelMixin for now
from rest_framework.mixins import ListModelMixin and CreateModelMixinBelow is how the ListModelMixin pattern works, if you look closely you can see that it creates a queryset, serializes the queryset and returns the serialized data. Just like what we do get a Product.
class ListModelMixin: """ List a queryset. """ def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset) if page is not None: 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)This is the mixin logic for creating a resource. ie the CreateModelMixin
class CreateModelMixin: """ Create a model instance. """ def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) 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): serializer.save()
def get_success_headers(self, data): try: return {'Location': str(data[api_settings.URL_FIELD_NAME])} except (TypeError, KeyError): return {}