【问题标题】:What is the different between save(), create() and update () in django rest framework?django rest框架中的save()、create()和update()有什么区别?
【发布时间】:2017-12-19 09:50:34
【问题描述】:

我在使用序列化程序在 django rest 框架上制作 api 时感到困惑,请告诉我 save()、create() 和 update() 方法之间的确切区别,我的代码示例如下,

View.py

class AddUser(views.APIView):
    serializer_class = UserForAdminSerializer

    def post(self, request, *args, **kwargs):

        serializer = UserForAdminSerializer(data=request.data)

        if serializer.is_valid():

            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializers.py

class UserForAdminSerializer(serializers.ModelSerializer):

    first_name = serializers.CharField(max_length=30)
    last_name = serializers.CharField(max_length=30)
    name = serializers.CharField(max_length=30)
    password = serializers.CharField(max_length=20, style={'input_type': 'password'})

    class Meta:
        model = User
        fields = ('id', 'url', 'first_name', 'last_name', 'name', 'username', 'email', 'password',
                  'total_exp_year', 'total_exp_month', 'voteup_count', 'is_featured',
                  'is_active', 'headline', 'description', 'profile_picture', )

    def create(self, validated_data):
        password = validated_data.pop('password', None)
        instance = self.Meta.model(**validated_data)
        if password is not None:
            instance.set_password(password)
        instance.save()
        return instance

在 view.py 文件中的上述代码上,我使用了 save() 方法,而 serializers.py 使用了 save() 或 update() 方法,所以请解释一下它是如何工作的,并清除我在 save() 和 create() 之间的混淆

【问题讨论】:

    标签: django python-3.x django-rest-framework


    【解决方案1】:

    在 Django Rest Framework documentation 中,他们非常清楚地解释了何时覆盖保存方法和何时创建方法。

    为了您的方便,我在这里发布他们的解释


    在某些情况下,.create() 和 .update() 方法名称可能没有意义。例如,在联系表单中,我们可能不会创建新实例,而是发送电子邮件或其他消息。 在这些情况下,您可能会选择直接覆盖 .save() ,因为它更具可读性和意义。
    示例:-

    class ContactForm(serializers.Serializer):
        email = serializers.EmailField()
        message = serializers.CharField()
    
        def save(self):
            email = self.validated_data['email']
            message = self.validated_data['message']
            send_email(from=email, message=message)
    

    【讨论】:

    【解决方案2】:

    通常最好的理解代码的方法是实际阅读它,所以让我们看看source

    class BaseSerializer(Field):
        ...
        def update(self, instance, validated_data):
            raise NotImplementedError('`update()` must be implemented.')
    
        def create(self, validated_data):
            raise NotImplementedError('`create()` must be implemented.')
    
        def save(self, **kwargs):
            ...
            ... a lot of assertions and safety checks ...
            ... 
    
            validated_data = dict(
                list(self.validated_data.items()) +
                list(kwargs.items())
            )
    
            if self.instance is not None:
                self.instance = self.update(self.instance, validated_data)
                ....
            else:
                self.instance = self.create(validated_data)
                ...
            return self.instance
    

    好的,所以,在这个基类中,方法 updatecreate 留给具体的子类来实现(因为对于序列化程序,例如 ListSerializerModelSerializer,细节会有所不同)。

    然而,save 已实现,它基本上只是检查对象是新的还是现有的 (if self.instance is not None) 并分别调用 updatecreate代码将在每个其他序列化程序中调用。

    我们来看看具体的子类:

    def create(self, validated_data):
        ...
        ... some stuff happening
        ...
    
        try:
            # Here is the important part! Creating new object!
            instance = ModelClass.objects.create(**validated_data)
        except TypeError:
            raise TypeError(msg)
    
        # Save many-to-many relationships after the instance is created.
        if many_to_many:
            for field_name, value in many_to_many.items():
                set_many(instance, field_name, value)
    
        return instance
    
    
    def update(self, instance, validated_data):
        raise_errors_on_nested_writes('update', self, validated_data)
        info = model_meta.get_field_info(instance)
    
        # Simply set each attribute on the instance, and then save it.
        # Note that unlike `.create()` we don't need to treat many-to-many
        # relationships as being a special case. During updates we already
        # have an instance pk for the relationships to be associated with.
        for attr, value in validated_data.items():
            if attr in info.relations and info.relations[attr].to_many:
                set_many(instance, attr, value)
            else:
                setattr(instance, attr, value)
        instance.save()
    
        return instance
    

    您可以看到createupdate 调用set_many(instance, attr, value) 来设置对象属性的值。但是,create 之前会进行一次 critical 调用:ModelClass.objects.create(**validated_data)。这实际上创建了新实例。

    我希望这能澄清一点。

    【讨论】:

    • 感谢 Siegmeyer :)
    • 你能解释一下更新定义中self和instance有什么区别吗?
    • @LittleBrain 对于任何想知道未来的人来说,self 实际上是序列化器的当前实例,因为实例是序列化器引用的模型的实例。所以 Serializer 的 update() 方法实现了 Serializer 应该如何操作模型实例。
    猜你喜欢
    • 2017-07-25
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 2019-04-18
    • 1970-01-01
    • 2019-07-09
    • 2019-07-03
    相关资源
    最近更新 更多