如何解决更新相关对象 django rest 框架
在我的 django 项目中,我有 2 个相关模型:
class User(AbstractUser):
email = models.EmailField(
verbose_name='e-mailaddress',max_length=255,unique=True)
# other props not important
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE)
#other props not important
对于创建和检索,在序列化器中将 User 作为嵌套对象很方便:
class ProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Profile
fields = '__all__'
def create(self,validated_data):
user_data = validated_data.pop('user')
user = User.objects.create(**user_data)
user.save()
# because of reasons,an empty profile is created on initial save. This works,trust me
d,_ = Profile.objects.update_or_create(user=user,defaults=validated_data)
d.save()
return d
然而。我还希望实现的一项操作是同时更新配置文件和用户的属性。使用我的序列化程序执行此操作时,serializer.is_valid()
失败,因为数据库中已存在提供的电子邮件。这也表明,即使验证通过(即由于更新的电子邮件地址),也会创建一个新的用户对象并将其耦合到配置文件。所以我的问题是:
如何验证序列化程序检查嵌套对象的编辑是否有效,而不是检查是否可以创建新对象?
解决方法
您可以通过执行类似操作来更新配置文件及其相关用户的属性。
class ProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = Profile
fields = '__all__'
def update(self,instance,validated_data):
# update the profile-related fields here.
# the other properties which you didn't mention.
...
profile = instance
# get the profile object
...
instance.save()
user = validated_data.get('user')
# get the related user.
# update the user properties here,like:
user.email = 'UPDATED_EMAIL'
user.save() # you need to save the user as well as the profile!
return instance
,
我设法自己找到了一些解决方法。使用序列化器字段的 source
属性,可以将相关对象的某些属性添加到序列化器中。就我而言,我能够将以下几行添加到 ProfileSerializer 中以实现我需要的功能:
first_name = serializers.CharField(max_length=30,source='user.first_name',required=False)
last_name = serializers.CharField(max_length=150,source='user.last_name',required=False)
email = serializers.CharField(max_length=255,source='user.email')
User
有更多的属性,但对于我目前的要求,我不需要它们,这很好用(尽管如果需要所有属性,为所有属性添加这样一行会很乏味)。它确实需要 create
和 update
函数的自定义实现,但我认为无论如何都会需要这些。我个人使用过:
def create(self,validated_data):
user_data = validated_data.pop('user')
user = User.objects.create(**user_data)
user.save()
instance = ...
return instance
def update(self,validated_data):
user_data = validated_data.pop('user')
user = instance.user
for k,v in user_data.items():
setattr(user,k,v)
user.save()
...
return instance
注意:django-rest 自动将具有共享源对象的属性分组到嵌套对象中:{'user': {'email': ...,'first_name': ...,'last_name': ...},'phone_number': ...}
(其中 phone_number
是配置文件属性)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。