1

我需要有关使用 Django 休息框架的 PATCH 请求的帮助。

我有一个User继承自AbstractBaseUser其中的模型,它有 2 个字段:nameemail. 该email领域是独一无二的。

然后我有一个DojoMaster与模型具有 OneToOne 关系的User模型:

models.py

class DojoMaster(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
    phone = models.BigIntegerField()
    username = models.CharField(max_length=100, unique=True)
    country = models.ForeignKey(Country, on_delete=models.CASCADE)

我可以向应用程序发布“dojomaster”。假设“dojomaster” POST 如下所示:

POST payload

{
    "user": {
        "name": "XYZ",
        "email": "xyz@mail.com",
        "password": "2He$8Mv*"
    },
    "phone": 2685211,
    "country": 575,
    "username": "iAmXyZ"
} 

现在“dojomaster”想要更改其中一些细节,因此发送了一个 PATCH 请求:

PATCH payload

{
    "user": {
        "name": "XYZ",
        "email": "xyz24@mail.com", #change email
        "password": "p@55w0rd" #change password
    },
    "phone": 3972925, #change phone number
    "country": 575,
    "username": "iAmXyZ"
} 

为了实现这一点,我在我的serializers.py

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('name', 'email', 'password')

class DojoMasterUpdateSerializer(serializers.ModelSerializer):
    user = UserSerializer(required=True)

    def update(self, instance, validated_data):
        user_data = validated_data.pop('user')
        user = User.objects.update(**user_data)
        instance.user = validated_data.get('user', user)
        instance.username = validated_data.get('username', instance.username)
        instance.phone = validated_data.get('phone', instance.phone)
        instance.country = Country.objects.get(
            country=validated_data.get('country', instance.country)
        )
        instance.save()
        return instance

    class Meta:
        model = DojoMaster
        fields = ('user', 'country', 'phone', 'username')
        write_only_fields = ('password',)

为了使用序列化程序,我创建了以下视图:

views.py

class DojoMasterUpdateView(generics.UpdateAPIView):
    queryset = DojoMaster.objects.all()
    serializer_class = DojoMasterUpdateSerializer

但是,当我这样做时,我收到Status: 400 Bad Request以下有效负载的错误:

{
    "user": {
        "email": [
            "user with this email already exists."
        ]
    }
}

我也尝试过使用 PUT 请求但没有成功。

如何使用 DRF 修补具有此类 OneToOneField 关系的实体?您的帮助将不胜感激。

4

1 回答 1

2

这个问题很老,你可能已经找到了答案。

但是,如果有人想知道:

问题是这样的:

user = User.objects.update(**user_data)

这样,您不会更新用户的一个实例 - 您正在尝试使用 user_data 更新 User 表中的所有用户。

由于您正在修补 DojoMaster 的实例,因此您应该已经拥有属于它的 user 实例:

因此,您的更新方法可能如下所示:

def update(self, instance, validated_data):
    user_data = validated_data.pop('user')
    user_ser = UserSerializer(instance=instance.user, data=user_data)
    if user_ser.is_valid():
        user_ser.save()
    instance.username = validated_data.get('username', instance.username)
    instance.phone = validated_data.get('phone', instance.phone)
    instance.save()
    return instance
于 2018-07-25T07:35:40.257 回答