Python 更新相关对象django rest框架

Python 更新相关对象django rest框架,python,django,django-rest-framework,one-to-one,Python,Django,Django Rest Framework,One To One,在我的django项目中,我有两个相关模型: 类用户(抽象用户): email=models.EmailField( 详细的_name='e-mailaddress', 最大长度=255, 唯一性=真) #其他道具不重要 类配置文件(models.Model): user=models.OneToOneField(settings.AUTH\u user\u MODEL,on\u delete=models.CASCADE) #其他道具不重要 对于创建和检索,将用户作为序列化程序中的嵌套对象很

在我的django项目中,我有两个相关模型:

类用户(抽象用户):
email=models.EmailField(
详细的_name='e-mailaddress',
最大长度=255,
唯一性=真)
#其他道具不重要
类配置文件(models.Model):
user=models.OneToOneField(settings.AUTH\u user\u MODEL,on\u delete=models.CASCADE)
#其他道具不重要
对于创建和检索,将用户作为序列化程序中的嵌套对象很方便:

class ProfileSerializer(serializers.ModelSerializer):
user=UserSerializer()
类元:
模型=外形
字段='\uuuu所有\uuuu'
def创建(自我验证的_数据):
user\u data=validated\u data.pop('用户')
user=user.objects.create(**user\u数据)
user.save()
#由于各种原因,初始保存时会创建一个空配置文件。相信我,这是有效的
d、 _u=Profile.objects.update_或_create(用户=user,默认值=validated_数据)
d、 保存()
返回d
不过。我也希望可以执行的一个操作是同时更新配置文件和用户的属性。使用我的序列化程序执行此操作时,
serializer.is\u valid()
失败,因为提供的电子邮件已存在于数据库中。这还表明,即使验证通过(即,由于更新的电子邮件地址),也将创建新的用户对象并将其耦合到配置文件。所以我的问题是:


如何验证序列化程序检查嵌套对象的编辑是否有效,而不是检查是否可以创建新对象?您可以通过执行类似操作来更新配置文件及其相关用户的属性

class ProfileSerializer(serializers.ModelSerializer):
user=UserSerializer()
类元:
模型=外形
字段='\uuuu所有\uuuu'
def更新(自身、实例、已验证的_数据):
#在此更新配置文件相关字段。
#你没有提到的其他财产。
...
profile=实例
#获取配置文件对象
...
save()实例
user=validated\u data.get('user'))
#获取相关用户。
#在此处更新用户属性,如:
user.email='UPDATED_email'
user.save()#您需要保存用户和配置文件!
返回实例

您可以通过执行类似操作来更新配置文件及其相关用户的属性

class ProfileSerializer(serializers.ModelSerializer):
user=UserSerializer()
类元:
模型=外形
字段='\uuuu所有\uuuu'
def更新(自身、实例、已验证的_数据):
#在此更新配置文件相关字段。
#你没有提到的其他财产。
...
profile=实例
#获取配置文件对象
...
save()实例
user=validated\u data.get('user'))
#获取相关用户。
#在此处更新用户属性,如:
user.email='UPDATED_email'
user.save()#您需要保存用户和配置文件!
返回实例

我自己设法找到了解决办法。使用序列化程序字段的
source
属性,可以将相关对象中的某些属性添加到序列化程序中。在我的例子中,我能够为ProfileSerializer添加以下行以实现所需的功能:

first\u name=serializers.CharField(最大长度=30,source='user.first\u name',必需=False)
last_name=serializers.CharField(最大长度=150,source='user.last_name',必需=False)
email=serializers.CharField(最大长度=255,source='user.email')
用户
有更多属性,但对于我当前的需求,我不需要它们,这很好(尽管如果需要所有属性,为所有属性添加这样一行会很乏味)。它确实需要一个
create
update
函数的自定义实现,但我认为无论如何都需要这些函数。我个人使用:

def创建(自我验证的_数据):
user\u data=validated\u data.pop('用户')
user=user.objects.create(**user\u数据)
user.save()
实例=。。。
返回实例
def更新(自身、实例、已验证的_数据):
user\u data=validated\u data.pop('用户')
user=instance.user
对于用户_data.items()中的k,v:
setattr(用户、k、v)
user.save()
...
返回实例

注意:django rest自动将具有共享源对象的属性分组到嵌套对象中:
{'user':{'email':…,'first_name':…,'last_name':…},'phone_number':…}
(其中,
phone_number
是配置文件属性)

我自己设法找到了一些解决方法。使用序列化程序字段的
source
属性,可以将相关对象中的某些属性添加到序列化程序中。在我的例子中,我能够为ProfileSerializer添加以下行以实现所需的功能:

first\u name=serializers.CharField(最大长度=30,source='user.first\u name',必需=False)
last_name=serializers.CharField(最大长度=150,source='user.last_name',必需=False)
email=serializers.CharField(最大长度=255,source='user.email')
用户
有更多属性,但对于我当前的需求,我不需要它们,这很好(尽管如果需要所有属性,为所有属性添加这样一行会很乏味)。它确实需要一个
create
update
函数的自定义实现,但我认为无论如何都需要这些函数。我个人使用:

def创建(自我验证的_数据):
user\u data=validated\u data.pop('用户')
user=user.objects.create(**user\u数据)
user.save()
实例=。。。
ret