aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework/mixins.py
diff options
context:
space:
mode:
Diffstat (limited to 'rest_framework/mixins.py')
-rw-r--r--rest_framework/mixins.py50
1 files changed, 34 insertions, 16 deletions
diff --git a/rest_framework/mixins.py b/rest_framework/mixins.py
index 9bd566da..e0ae216e 100644
--- a/rest_framework/mixins.py
+++ b/rest_framework/mixins.py
@@ -3,9 +3,6 @@ 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.
-
-Eg. Use mixins to build a Resource class, and have a Router class
- perform the binding of http methods to actions for us.
"""
from django.http import Http404
from rest_framework import status
@@ -18,30 +15,42 @@ class CreateModelMixin(object):
Should be mixed in with any `BaseView`.
"""
def create(self, request, *args, **kwargs):
- serializer = self.get_serializer(data=request.DATA)
+ serializer = self.get_serializer(data=request.DATA, files=request.FILES)
+
if serializer.is_valid():
self.pre_save(serializer.object)
self.object = serializer.save()
- return Response(serializer.data, status=status.HTTP_201_CREATED)
+ headers = self.get_success_headers(serializer.data)
+ return Response(serializer.data, status=status.HTTP_201_CREATED,
+ headers=headers)
+
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+ def get_success_headers(self, data):
+ try:
+ return {'Location': data['url']}
+ except (TypeError, KeyError):
+ return {}
+
class ListModelMixin(object):
"""
List a queryset.
- Should be mixed in with `MultipleObjectBaseView`.
+ Should be mixed in with `MultipleObjectAPIView`.
"""
empty_error = u"Empty list and '%(class_name)s.allow_empty' is False."
def list(self, request, *args, **kwargs):
- self.object_list = self.get_queryset()
+ queryset = self.get_queryset()
+ self.object_list = self.filter_queryset(queryset)
# Default is to allow empty querysets. This can be altered by setting
# `.allow_empty = False`, to raise 404 errors on empty querysets.
allow_empty = self.get_allow_empty()
- if not allow_empty and len(self.object_list) == 0:
- error_args = {'class_name': self.__class__.__name__}
- raise Http404(self.empty_error % error_args)
+ if not allow_empty and not self.object_list:
+ class_name = self.__class__.__name__
+ error_msg = self.empty_error % {'class_name': class_name}
+ raise Http404(error_msg)
# Pagination size is set by the `.paginate_by` attribute,
# which may be `None` to disable pagination.
@@ -51,7 +60,7 @@ class ListModelMixin(object):
paginator, page, queryset, is_paginated = packed
serializer = self.get_pagination_serializer(page)
else:
- serializer = self.get_serializer(instance=self.object_list)
+ serializer = self.get_serializer(self.object_list)
return Response(serializer.data)
@@ -63,7 +72,7 @@ class RetrieveModelMixin(object):
"""
def retrieve(self, request, *args, **kwargs):
self.object = self.get_object()
- serializer = self.get_serializer(instance=self.object)
+ serializer = self.get_serializer(self.object)
return Response(serializer.data)
@@ -73,17 +82,21 @@ class UpdateModelMixin(object):
Should be mixed in with `SingleObjectBaseView`.
"""
def update(self, request, *args, **kwargs):
+ partial = kwargs.pop('partial', False)
try:
self.object = self.get_object()
+ success_status_code = status.HTTP_200_OK
except Http404:
self.object = None
+ success_status_code = status.HTTP_201_CREATED
- serializer = self.get_serializer(data=request.DATA, instance=self.object)
+ serializer = self.get_serializer(self.object, data=request.DATA,
+ files=request.FILES, partial=partial)
if serializer.is_valid():
self.pre_save(serializer.object)
self.object = serializer.save()
- return Response(serializer.data)
+ return Response(serializer.data, status=success_status_code)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@@ -101,6 +114,11 @@ class UpdateModelMixin(object):
slug_field = self.get_slug_field()
setattr(obj, slug_field, slug)
+ # Ensure we clean the attributes so that we don't eg return integer
+ # pk using a string representation, as provided by the url conf kwarg.
+ if hasattr(obj, 'full_clean'):
+ obj.full_clean()
+
class DestroyModelMixin(object):
"""
@@ -108,6 +126,6 @@ class DestroyModelMixin(object):
Should be mixed in with `SingleObjectBaseView`.
"""
def destroy(self, request, *args, **kwargs):
- self.object = self.get_object()
- self.object.delete()
+ obj = self.get_object()
+ obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)