Skip to content

Commit

Permalink
Added a post_save hook. Closes encode#558.
Browse files Browse the repository at this point in the history
  • Loading branch information
tomchristie committed Feb 6, 2013
1 parent 123c6cb commit c18fb0d
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
9 changes: 9 additions & 0 deletions docs/api-guide/generic-views.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ Each of the generic views provided is built by combining one of the base views b

Extends REST framework's `APIView` class, adding support for serialization of model instances and model querysets.

**Methods**:

* `get_serializer_context(self)` - Returns a dictionary containing any extra context that should be supplied to the serializer. Defaults to including `'request'`, `'view'` and `'format'` keys.
* `get_serializer_class(self)` - Returns the class that should be used for the serializer.
* `get_serializer(self, instance=None, data=None, files=None, many=False, partial=False)` - Returns a serializer instance.
* `pre_save(self, obj)` - A hook that is called before saving an object.
* `post_save(self, obj, created=False)` - A hook that is called after saving an object.


**Attributes**:

* `model` - The model that should be used for this view. Used as a fallback for determining the serializer if `serializer_class` is not set, and as a fallback for determining the queryset if `queryset` is not set. Otherwise not required.
Expand Down
1 change: 1 addition & 0 deletions docs/topics/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ You can determine your currently installed version using `pip freeze`:

### Master

* Added a `post_save()` hook to the generic views.
* Bugfix: Fix styling on browsable API login.
* Bugfix: Fix issue with deserializing empty to-many relations.
* Bugfix: Ensure model field validation is still applied for ModelSerializer subclasses with an custom `.restore_object()` method.
Expand Down
16 changes: 15 additions & 1 deletion rest_framework/generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class Meta:
return serializer_class

def get_serializer(self, instance=None, data=None,
files=None, partial=False, many=False):
files=None, many=False, partial=False):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
Expand All @@ -58,6 +58,20 @@ def get_serializer(self, instance=None, data=None,
return serializer_class(instance, data=data, files=files,
many=many, partial=partial, context=context)

def pre_save(self, obj):
"""
Placeholder method for calling before saving an object.
May be used eg. to set attributes on the object that are implicit
in either the request, or the url.
"""
pass

def post_save(self, obj, created=False):
"""
Placeholder method for calling after saving an object.
"""
pass


class MultipleObjectAPIView(MultipleObjectMixin, GenericAPIView):
"""
Expand Down
12 changes: 7 additions & 5 deletions rest_framework/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def create(self, request, *args, **kwargs):
if serializer.is_valid():
self.pre_save(serializer.object)
self.object = serializer.save()
self.post_save(self.object, created=True)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED,
headers=headers)
Expand All @@ -34,9 +35,6 @@ def get_success_headers(self, data):
except (TypeError, KeyError):
return {}

def pre_save(self, obj):
pass


class ListModelMixin(object):
"""
Expand Down Expand Up @@ -88,19 +86,23 @@ class UpdateModelMixin(object):
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
self.object = None
try:
self.object = self.get_object()
success_status_code = status.HTTP_200_OK
except Http404:
self.object = None
created = True
success_status_code = status.HTTP_201_CREATED
else:
created = False
success_status_code = status.HTTP_200_OK

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()
self.post_save(self.object, created=created)
return Response(serializer.data, status=success_status_code)

return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Expand Down

0 comments on commit c18fb0d

Please sign in to comment.