django-rest-framework/rest_framework/mixins.py

101 lines
3.1 KiB
Python
Raw Permalink Normal View History

"""
Basic building blocks for generic class based views.
We don't bind behaviour to http method handlers yet,
which allows mixin classes to be composed in interesting ways.
"""
from django.db.models.query import prefetch_related_objects
from rest_framework import status
from rest_framework.response import Response
2014-01-15 00:35:09 +04:00
from rest_framework.settings import api_settings
class CreateModelMixin:
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
2014-09-26 13:46:52 +04:00
serializer = self.get_serializer(data=request.data)
2014-09-05 19:29:46 +04:00
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
2014-09-05 19:29:46 +04:00
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
2014-10-07 20:21:12 +04:00
serializer.save()
2012-11-14 16:24:20 +04:00
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
class ListModelMixin:
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
2015-01-09 18:30:36 +03:00
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
2013-04-25 20:40:17 +04:00
if page is not None:
2015-01-09 18:30:36 +03:00
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)
class RetrieveModelMixin:
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
2014-09-05 19:29:46 +04:00
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
class UpdateModelMixin:
"""
Update a model instance.
"""
2013-05-18 01:09:23 +04:00
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
2014-09-05 19:29:46 +04:00
instance = self.get_object()
2014-09-26 13:46:52 +04:00
serializer = self.get_serializer(instance, data=request.data, partial=partial)
2014-09-05 19:29:46 +04:00
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
2016-10-11 13:07:40 +03:00
queryset = self.filter_queryset(self.get_queryset())
if queryset._prefetch_related_lookups:
2016-10-11 13:07:40 +03:00
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance,
# and then re-prefetch related objects
instance._prefetched_objects_cache = {}
prefetch_related_objects([instance], *queryset._prefetch_related_lookups)
2016-10-11 13:07:40 +03:00
2014-09-05 19:29:46 +04:00
return Response(serializer.data)
def perform_update(self, serializer):
2014-10-07 20:21:12 +04:00
serializer.save()
2014-09-05 19:29:46 +04:00
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
2013-05-18 01:09:23 +04:00
class DestroyModelMixin:
2014-09-05 19:29:46 +04:00
"""
Destroy a model instance.
"""
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
2014-09-05 19:29:46 +04:00
return Response(status=status.HTTP_204_NO_CONTENT)
2012-10-08 15:52:56 +04:00
def perform_destroy(self, instance):
instance.delete()