From 280bd93f09aa74fea686c978ea2f8889b16cdc97 Mon Sep 17 00:00:00 2001 From: Steve Komarov Date: Fri, 20 Mar 2015 17:25:52 -0400 Subject: [PATCH] added hooks perform_list and perform_retrieve --- docs/api-guide/generic-views.md | 13 +++++++++++-- rest_framework/mixins.py | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index 7df3d6ff8..5e9e96a38 100644 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -166,13 +166,15 @@ For example: return 20 return 100 -**Save and deletion hooks**: +**Save, deletion, and retrieval hooks**: The following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior. * `perform_create(self, serializer)` - Called by `CreateModelMixin` when saving a new object instance. * `perform_update(self, serializer)` - Called by `UpdateModelMixin` when saving an existing object instance. * `perform_destroy(self, instance)` - Called by `DestroyModelMixin` when deleting an object instance. +* `perform_retrieve(self, serializer)` - Called by `RetrieveModelMixin` when retrieving an object instance. +* `perform_list(self, serializer)` - Called by `ListModelMixin` when listing multiple object instances. These hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument. @@ -184,8 +186,15 @@ These override points are also particularly useful for adding behavior that occu def perform_update(self, serializer): instance = serializer.save() send_email_confirmation(user=self.request.user, modified=instance) - + **Note**: These methods replace the old-style version 2.x `pre_save`, `post_save`, `pre_delete` and `post_delete` methods, which are no longer available. + +The `perform_list` and `perform_retrieve` hooks are useful for logging requests that have already passed the permission and serialization stages. + + def perform_retrieve(self, serializer): + log_user_accessed_item(user=self.request.user, item=serializer) + + **Other methods**: diff --git a/rest_framework/mixins.py b/rest_framework/mixins.py index c34cfcee1..8789ced5f 100644 --- a/rest_framework/mixins.py +++ b/rest_framework/mixins.py @@ -41,11 +41,19 @@ class ListModelMixin(object): page = self.paginate_queryset(queryset) if page is not None: serializer = self.get_serializer(page, many=True) + self.perform_list(serializer) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True) + self.perform_list(serializer) return Response(serializer.data) + def perform_list(self, serializer): + """ + Hook in the list method that can be overridden + """ + pass + class RetrieveModelMixin(object): """ @@ -54,8 +62,15 @@ class RetrieveModelMixin(object): def retrieve(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) + self.perform_retrieve(serializer) return Response(serializer.data) + def perform_retrieve(self, serializer): + """ + Hook in the retrieve method that can be overridden + """ + pass + class UpdateModelMixin(object): """