如何创建含新User的Vendor?解决Django序列化器create()参数报错
解决嵌套OneToOne序列化器创建对象的错误
这个错误其实是因为你调用User.objects.create()的方式完全不对——你不需要把UserSerializer实例传进去,create()方法只需要接收模型字段对应的关键字参数就行。不用重写UserSerializer的create方法,咱们直接改VendorSerializer的create逻辑就能解决问题,具体步骤如下:
1. 修正User对象的创建逻辑
你之前写的User.objects.create(UserSerializer(),validated_data=user_data)是典型的用法错误:
User.objects.create()不需要传入序列化器实例- 这个方法也没有
validated_data这个参数,它只接受模型字段的键值对
因为你在VendorSerializer里把user字段设为UserSerializer(required=True),DRF已经自动帮你校验了user_data的合法性,所以直接用字典解包的方式创建User即可:
user = User.objects.create(**user_data)
2. 简化Vendor的创建/更新逻辑
你原来的update_or_create写法太繁琐,还存在逻辑错误:你已经把user相关的数据从validated_data里pop成user_data了,validated_data里已经没有user这个键,再执行validated_data.pop('user')会抛出KeyError。
正确的做法是用刚才创建好的user对象作为唯一匹配条件,剩下的validated_data直接传给defaults参数:
vendor, created = Vendor.objects.update_or_create( user=user, defaults=validated_data )
这样既简洁,又避免了手动逐个pop字段的麻烦。
修正后的完整VendorSerializer代码
class VendorSerializer(serializers.ModelSerializer): user = UserSerializer(required=True) class Meta: model = Vendor fields = ('user','no_rue','adresse','code_postal','ville','pays') def create(self, validated_data): # 取出已验证的用户数据 user_data = validated_data.pop('user') # 创建User对象 user = User.objects.create(**user_data) # 创建或更新Vendor,关联刚创建的User vendor, created = Vendor.objects.update_or_create( user=user, defaults=validated_data ) return vendor
补充说明
如果你的User模型有必填字段(比如密码)没有包含在UserSerializer的fields里,你需要额外处理:
- 可以在
UserSerializer里添加密码字段,设置为write_only=True:class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True) class Meta: model = User fields = ('first_name', 'last_name', 'email', 'username', 'password') - 然后在创建User时加密密码:
from django.contrib.auth.hashers import make_password user = User.objects.create( **user_data, password=make_password(user_data.pop('password')) )
内容的提问来源于stack exchange,提问作者Hugo Mocho
相关产品推荐
相关产品推荐

