mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	Tweak pre/post save hooks. Return instance in .update().
This commit is contained in:
		
							parent
							
								
									af0f01c5b6
								
							
						
					
					
						commit
						0cbb57b40f
					
				| 
						 | 
				
			
			@ -116,11 +116,12 @@ This would now be split out into two separate methods.
 | 
			
		|||
        instance.language = validated_data.get('language', instance.language)
 | 
			
		||||
        instance.style = validated_data.get('style', instance.style)
 | 
			
		||||
        instance.save()
 | 
			
		||||
        return instance
 | 
			
		||||
 | 
			
		||||
	def create(self, validated_data):
 | 
			
		||||
        return Snippet.objects.create(**validated_data)
 | 
			
		||||
 | 
			
		||||
Note that the `.create` method should return the newly created object instance.
 | 
			
		||||
Note that these methods should return the newly created object instance.
 | 
			
		||||
 | 
			
		||||
#### Use `.validated_data` instead of `.object`.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -592,18 +593,27 @@ The `UniqueTogetherValidator` should be applied to a serializer, and takes a `qu
 | 
			
		|||
 | 
			
		||||
The view logic for the default method handlers has been significantly simplified, due to the new serializers API.
 | 
			
		||||
 | 
			
		||||
#### Removal of pre/post save hooks. 
 | 
			
		||||
#### Changes to pre/post save hooks. 
 | 
			
		||||
 | 
			
		||||
The following method hooks no longer exist on the new, simplified, generic views: `pre_save`, `post_save`, `pre_delete`, `post_delete`.
 | 
			
		||||
The `pre_save` and `post_save` hooks no longer exist, but are replaced with `perform_create(self, serializer)` and `perform_update(self, serializer)`.
 | 
			
		||||
 | 
			
		||||
If you do need custom behavior, you might choose to instead override the `.save()` method on your serializer class. For example:
 | 
			
		||||
These method should save the object instance by calling `serializer.save()`, adding in any explicit additional arguments as required. They may also perform any custom pre-save or post-save behavior.
 | 
			
		||||
 | 
			
		||||
    def save(self, *args, **kwargs):
 | 
			
		||||
        instance = super(MySerializer).save(*args, **kwarg)
 | 
			
		||||
For example:
 | 
			
		||||
 | 
			
		||||
    def perform_create(self, serializer):
 | 
			
		||||
        # Include the owner attribute directly, rather than from request data.
 | 
			
		||||
        instance = serializer.save(owner=self.request.user)
 | 
			
		||||
        # Perform a custom post-save action.
 | 
			
		||||
        send_email(instance.to_email, instance.message)
 | 
			
		||||
		return instance
 | 
			
		||||
 | 
			
		||||
Alternatively write your view logic exlpicitly, or tie your pre/post save behavior into the model class or model manager.
 | 
			
		||||
The `pre_delete` and `post_delete` hooks no longer exist, and are replaced with `.perform_destroy(self, instance)`, which should delete the instance and perform any custom actions.
 | 
			
		||||
 | 
			
		||||
    def perform_destroy(self, instance):
 | 
			
		||||
        # Perform a custom pre-delete action.
 | 
			
		||||
        send_deletion_alert(user=instance.created_by, deleted=instance)
 | 
			
		||||
        # Delete the object instance.
 | 
			
		||||
        instance.delete()
 | 
			
		||||
 | 
			
		||||
#### Removal of view attributes.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,11 +20,11 @@ class CreateModelMixin(object):
 | 
			
		|||
    def create(self, request, *args, **kwargs):
 | 
			
		||||
        serializer = self.get_serializer(data=request.data)
 | 
			
		||||
        serializer.is_valid(raise_exception=True)
 | 
			
		||||
        self.create_valid(serializer)
 | 
			
		||||
        self.perform_create(serializer)
 | 
			
		||||
        headers = self.get_success_headers(serializer.data)
 | 
			
		||||
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
 | 
			
		||||
 | 
			
		||||
    def create_valid(self, serializer):
 | 
			
		||||
    def perform_create(self, serializer):
 | 
			
		||||
        serializer.save()
 | 
			
		||||
 | 
			
		||||
    def get_success_headers(self, data):
 | 
			
		||||
| 
						 | 
				
			
			@ -67,10 +67,10 @@ class UpdateModelMixin(object):
 | 
			
		|||
        instance = self.get_object()
 | 
			
		||||
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
 | 
			
		||||
        serializer.is_valid(raise_exception=True)
 | 
			
		||||
        self.update_valid(serializer)
 | 
			
		||||
        self.preform_update(serializer)
 | 
			
		||||
        return Response(serializer.data)
 | 
			
		||||
 | 
			
		||||
    def update_valid(self, serializer):
 | 
			
		||||
    def preform_update(self, serializer):
 | 
			
		||||
        serializer.save()
 | 
			
		||||
 | 
			
		||||
    def partial_update(self, request, *args, **kwargs):
 | 
			
		||||
| 
						 | 
				
			
			@ -84,9 +84,12 @@ class DestroyModelMixin(object):
 | 
			
		|||
    """
 | 
			
		||||
    def destroy(self, request, *args, **kwargs):
 | 
			
		||||
        instance = self.get_object()
 | 
			
		||||
        instance.delete()
 | 
			
		||||
        self.perform_destroy(instance)
 | 
			
		||||
        return Response(status=status.HTTP_204_NO_CONTENT)
 | 
			
		||||
 | 
			
		||||
    def perform_destroy(self, instance):
 | 
			
		||||
        instance.delete()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# The AllowPUTAsCreateMixin was previously the default behaviour
 | 
			
		||||
# for PUT requests. This has now been removed and must be *explicitly*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,7 +83,10 @@ class BaseSerializer(Field):
 | 
			
		|||
            )
 | 
			
		||||
 | 
			
		||||
        if self.instance is not None:
 | 
			
		||||
            self.update(self.instance, validated_data)
 | 
			
		||||
            self.instance = self.update(self.instance, validated_data)
 | 
			
		||||
            assert self.instance is not None, (
 | 
			
		||||
                '`update()` did not return an object instance.'
 | 
			
		||||
            )
 | 
			
		||||
        else:
 | 
			
		||||
            self.instance = self.create(validated_data)
 | 
			
		||||
            assert self.instance is not None, (
 | 
			
		||||
| 
						 | 
				
			
			@ -444,19 +447,19 @@ class ModelSerializer(Serializer):
 | 
			
		|||
                self.validators.extend(validators)
 | 
			
		||||
                self._kwargs['validators'] = validators
 | 
			
		||||
 | 
			
		||||
    def create(self, attrs):
 | 
			
		||||
    def create(self, validated_attrs):
 | 
			
		||||
        ModelClass = self.Meta.model
 | 
			
		||||
 | 
			
		||||
        # Remove many-to-many relationships from attrs.
 | 
			
		||||
        # Remove many-to-many relationships from validated_attrs.
 | 
			
		||||
        # They are not valid arguments to the default `.create()` method,
 | 
			
		||||
        # as they require that the instance has already been saved.
 | 
			
		||||
        info = model_meta.get_field_info(ModelClass)
 | 
			
		||||
        many_to_many = {}
 | 
			
		||||
        for field_name, relation_info in info.relations.items():
 | 
			
		||||
            if relation_info.to_many and (field_name in attrs):
 | 
			
		||||
                many_to_many[field_name] = attrs.pop(field_name)
 | 
			
		||||
            if relation_info.to_many and (field_name in validated_attrs):
 | 
			
		||||
                many_to_many[field_name] = validated_attrs.pop(field_name)
 | 
			
		||||
 | 
			
		||||
        instance = ModelClass.objects.create(**attrs)
 | 
			
		||||
        instance = ModelClass.objects.create(**validated_attrs)
 | 
			
		||||
 | 
			
		||||
        # Save many-to-many relationships after the instance is created.
 | 
			
		||||
        if many_to_many:
 | 
			
		||||
| 
						 | 
				
			
			@ -465,10 +468,11 @@ class ModelSerializer(Serializer):
 | 
			
		|||
 | 
			
		||||
        return instance
 | 
			
		||||
 | 
			
		||||
    def update(self, obj, attrs):
 | 
			
		||||
        for attr, value in attrs.items():
 | 
			
		||||
            setattr(obj, attr, value)
 | 
			
		||||
        obj.save()
 | 
			
		||||
    def update(self, instance, validated_attrs):
 | 
			
		||||
        for attr, value in validated_attrs.items():
 | 
			
		||||
            setattr(instance, attr, value)
 | 
			
		||||
        instance.save()
 | 
			
		||||
        return instance
 | 
			
		||||
 | 
			
		||||
    def get_unique_together_validators(self):
 | 
			
		||||
        field_names = set([
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user