如何解决Django DRF注册接口报错:禁止直接赋值多对多字段groups?
错误原因
- 报错的核心是
groups是Person模型和Django内置Group模型之间的多对多关联字段 - Django不允许在创建主模型实例时直接给多对多字段赋值,因为多对多关联依赖主实例的主键写入中间关联表,必须等主实例成功保存到数据库后才能操作关联关系
修复步骤
- 先从校验后的数据中提取出
groups字段值,不要传入Person.objects.create()方法 - 主实例创建并保存完成后,调用多对多字段的
set()方法写入关联关系 - 额外优化:
set_password()方法本身会自动完成密码哈希,不需要嵌套make_password,否则会导致密码二次哈希,后续登录验证失败
修复后完整代码
class PersonSerializer(serializers.ModelSerializer): class Meta: model = Person fields = ('id', 'username', 'email', 'password', 'is_active', 'is_staff', 'is_superuser' , 'Designation', 'Address', 'groups', 'profile') def create(self, validated_data): # 先取出多对多字段groups的值,从validated_data中移除,默认空列表避免无传参时报错 groups = validated_data.pop('groups', []) # 创建用户实例时不再传入groups参数 user = Person.objects.create( username=validated_data['username'], email=validated_data['email'], password=validated_data['password'], Designation=validated_data['Designation'], is_active=validated_data['is_active'], is_staff=validated_data['is_staff'], is_superuser=validated_data['is_superuser'], Address=validated_data['Address'], profile=validated_data['profile'] ) # 直接传入明文密码即可,set_password自带哈希逻辑 user.set_password(validated_data['password']) user.save() # 主实例保存完成后,用set()方法设置多对多关联 user.groups.set(groups) return user
如果存在其他多对多字段,都按照上述逻辑处理即可:先弹出字段值,主实例保存完成后调用对应字段的set()方法赋值。
内容的提问来源于stack exchange,提问作者MOHAN SUNKA
相关产品推荐
相关产品推荐

