perform_create, perform_update, perform_destroy hooks

This commit is contained in:
Tom Christie 2014-11-26 09:04:48 +00:00
parent 31536566d7
commit c01c631ef2
2 changed files with 26 additions and 21 deletions

View File

@ -433,9 +433,9 @@ The method should accept a single argument (in addition to `self`), which is the
# Custom fields # Custom fields
If you want to create a custom field, you'll probably want to override either one or both of the `.to_native()` and `.from_native()` methods. These two methods are used to convert between the initial datatype, and a primitive, serializable datatype. Primitive datatypes may be any of a number, string, date/time/datetime or None. They may also be any list or dictionary like object that only contains other primitive objects. If you want to create a custom field, you'll probably want to override either one or both of the `.to_representation()` and `.to_internal_value()` methods. These two methods are used to convert between the initial datatype, and a primitive, serializable datatype. Primitive datatypes may be any of a number, string, date/time/datetime or None. They may also be any list or dictionary like object that only contains other primitive objects.
The `.to_native()` method is called to convert the initial datatype into a primitive, serializable datatype. The `from_native()` method is called to restore a primitive datatype into its initial representation. The `.to_representation()` method is called to convert the initial datatype into a primitive, serializable datatype. The `to_internal_value()` method is called to restore a primitive datatype into its internal python representation.
## Examples ## Examples
@ -450,25 +450,30 @@ Let's look at an example of serializing a class that represents an RGB color val
assert(red < 256 and green < 256 and blue < 256) assert(red < 256 and green < 256 and blue < 256)
self.red, self.green, self.blue = red, green, blue self.red, self.green, self.blue = red, green, blue
class ColourField(serializers.WritableField): class ColorField(serializers.Field):
""" """
Color objects are serialized into "rgb(#, #, #)" notation. Color objects are serialized into "rgb(#, #, #)" notation.
""" """
def to_native(self, obj): def to_representation(self, obj):
return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue) return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue)
def from_native(self, data): def to_internal_value(self, data):
data = data.strip('rgb(').rstrip(')') data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')] red, green, blue = [int(col) for col in data.split(',')]
return Color(red, green, blue) return Color(red, green, blue)
By default field values are treated as mapping to an attribute on the object. If you need to customize how the field value is accessed and set you need to override `.field_to_native()` and/or `.field_from_native()`. By default field values are treated as mapping to an attribute on the object. If you need to customize how the field value is accessed and set you need to override `.get_attribute()` and/or `.get_value()`.
As an example, let's create a field that can be used represent the class name of the object being serialized: As an example, let's create a field that can be used represent the class name of the object being serialized:
class ClassNameField(serializers.Field): class ClassNameField(serializers.Field):
def field_to_native(self, obj, field_name): def get_attribute(self, obj):
# We pass the object instance onto `to_representation`,
# not just the field attribute.
return obj
def to_representation(self, obj):
""" """
Serialize the object's class name. Serialize the object's class name.
""" """

View File

@ -7,7 +7,7 @@ source: mixins.py
> >
> &mdash; [Django Documentation][cite] > &mdash; [Django Documentation][cite]
One of the key benefits of class based views is the way they allow you to compose bits of reusable behaviour. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns. One of the key benefits of class based views is the way they allow you to compose bits of reusable behavior. REST framework takes advantage of this by providing a number of pre-built views that provide for commonly used patterns.
The generic views provided by REST framework allow you to quickly build API views that map closely to your database models. The generic views provided by REST framework allow you to quickly build API views that map closely to your database models.
@ -171,24 +171,24 @@ For example:
return 20 return 20
return 100 return 100
**Save / deletion hooks**: **Save and deletion hooks**:
The following methods are provided as placeholder interfaces. They contain empty implementations and are not called directly by `GenericAPIView`, but they are overridden and used by some of the mixin classes. The following methods are provided by the mixin classes, and provide easy overriding of the object save or deletion behavior.
* `pre_save(self, obj)` - A hook that is called before saving an object. * `perform_create(self, serializer)` - Called by `CreateModelMixin` when saving a new object instance.
* `post_save(self, obj, created=False)` - A hook that is called after saving an object. * `perform_update(self, serializer)` - Called by `UpdateModelMixin` when saving an existing object instance.
* `pre_delete(self, obj)` - A hook that is called before deleting an object. * `perform_destroy(self, instance)` - Called by `DestroyModelMixin` when deleting an object instance.
* `post_delete(self, obj)` - A hook that is called after deleting an object.
The `pre_save` method in particular is a useful hook 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. 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.
def pre_save(self, obj): def perform_create(self, serializer):
""" serializer.save(user=self.request.user)
Set the object's owner, based on the incoming request.
"""
obj.owner = self.request.user
Remember that the `pre_save()` method is not called by `GenericAPIView` itself, but it is called by `create()` and `update()` methods on the `CreateModelMixin` and `UpdateModelMixin` classes. These override points are also particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.
def perform_update(self, serializer):
instance = serializer.save()
send_email_confirmation(user=self.request.user, modified=instance)
**Other methods**: **Other methods**: