diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md index 17a65ab8e..1e856853a 100644 --- a/docs/api-guide/fields.md +++ b/docs/api-guide/fields.md @@ -433,9 +433,9 @@ The method should accept a single argument (in addition to `self`), which is the # 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 @@ -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) self.red, self.green, self.blue = red, green, blue - class ColourField(serializers.WritableField): + class ColorField(serializers.Field): """ 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) - def from_native(self, data): + def to_internal_value(self, data): data = data.strip('rgb(').rstrip(')') red, green, blue = [int(col) for col in data.split(',')] 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: 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. """ diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md index 489b628fc..dc51189c3 100755 --- a/docs/api-guide/generic-views.md +++ b/docs/api-guide/generic-views.md @@ -7,7 +7,7 @@ source: mixins.py > > — [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. @@ -171,24 +171,24 @@ For example: return 20 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. -* `post_save(self, obj, created=False)` - A hook that is called after saving an object. -* `pre_delete(self, obj)` - A hook that is called before deleting an object. -* `post_delete(self, obj)` - A hook that is called after deleting an object. +* `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. -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): - """ - Set the object's owner, based on the incoming request. - """ - obj.owner = self.request.user + def perform_create(self, serializer): + serializer.save(user=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**: