mixins.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. """
  2. Basic building blocks for generic class based views.
  3. We don't bind behaviour to http method handlers yet,
  4. which allows mixin classes to be composed in interesting ways.
  5. """
  6. from rest_framework import status
  7. from rest_framework.response import Response
  8. from rest_framework.settings import api_settings
  9. class CreateModelMixin:
  10. """
  11. Create a model instance.
  12. """
  13. def create(self, request, *args, **kwargs):
  14. serializer = self.get_serializer(data=request.data)
  15. serializer.is_valid(raise_exception=True)
  16. self.perform_create(serializer)
  17. headers = self.get_success_headers(serializer.data)
  18. return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
  19. def perform_create(self, serializer):
  20. serializer.save()
  21. def get_success_headers(self, data):
  22. try:
  23. return {'Location': str(data[api_settings.URL_FIELD_NAME])}
  24. except (TypeError, KeyError):
  25. return {}
  26. class ListModelMixin:
  27. """
  28. List a queryset.
  29. """
  30. def list(self, request, *args, **kwargs):
  31. queryset = self.filter_queryset(self.get_queryset())
  32. page = self.paginate_queryset(queryset)
  33. if page is not None:
  34. serializer = self.get_serializer(page, many=True)
  35. return self.get_paginated_response(serializer.data)
  36. serializer = self.get_serializer(queryset, many=True)
  37. return Response(serializer.data)
  38. class RetrieveModelMixin:
  39. """
  40. Retrieve a model instance.
  41. """
  42. def retrieve(self, request, *args, **kwargs):
  43. instance = self.get_object()
  44. serializer = self.get_serializer(instance)
  45. return Response(serializer.data)
  46. class UpdateModelMixin:
  47. """
  48. Update a model instance.
  49. """
  50. def update(self, request, *args, **kwargs):
  51. partial = kwargs.pop('partial', False)
  52. instance = self.get_object()
  53. serializer = self.get_serializer(instance, data=request.data, partial=partial)
  54. serializer.is_valid(raise_exception=True)
  55. self.perform_update(serializer)
  56. if getattr(instance, '_prefetched_objects_cache', None):
  57. # If 'prefetch_related' has been applied to a queryset, we need to
  58. # forcibly invalidate the prefetch cache on the instance.
  59. instance._prefetched_objects_cache = {}
  60. return Response(serializer.data)
  61. def perform_update(self, serializer):
  62. serializer.save()
  63. def partial_update(self, request, *args, **kwargs):
  64. kwargs['partial'] = True
  65. return self.update(request, *args, **kwargs)
  66. class DestroyModelMixin:
  67. """
  68. Destroy a model instance.
  69. """
  70. def destroy(self, request, *args, **kwargs):
  71. instance = self.get_object()
  72. self.perform_destroy(instance)
  73. return Response(status=status.HTTP_204_NO_CONTENT)
  74. def perform_destroy(self, instance):
  75. instance.delete()