更新DRF嵌套序列化器时触发confirm_password字段KeyError求助
问题解决方法
错误根源
更新UserProfile时,前端通常不会传入password和confirm_password(仅修改姓名、邮箱等信息),但AccountSerializer的validate方法直接通过data['confirm_password']取值,导致字段不存在时触发KeyError。
解决方案
方案1:区分创建/更新场景,仅创建时验证密码
修改AccountSerializer的逻辑,仅在创建新用户时验证密码匹配,更新时跳过不必要的密码验证:
class AccountSerializer(ModelSerializer): confirm_password = CharField(write_only=True, required=False) class Meta: model = Account fields = ["first_name", "last_name", "email", "password", "confirm_password"] extra_kwargs = { "password": {"write_only": True, "required": False}, } def validate(self, data): # 仅创建新用户且传入密码时,才验证密码与确认密码匹配 if not self.instance and 'password' in data: confirm_password = data.pop("confirm_password", None) if not confirm_password or data['password'] != confirm_password: raise ValidationError({"error": "Passwords do not match"}) return data def create(self, validated_data): user = Account.objects.create_user(**validated_data) return user def update(self, instance, validated_data): # 更新时若传入密码,使用set_password加密存储 password = validated_data.pop('password', None) if password: instance.set_password(password) return super().update(instance, validated_data)
方案2:简化UserprofileSerializer的更新逻辑
如果更新UserProfile时不需要修改密码,可直接在UserprofileSerializer中处理用户信息更新,避免触发AccountSerializer的完整验证:
class UserprofileSerializer(ModelSerializer): # 更新阶段用只读序列化器避免验证,创建时再用完整逻辑 user = AccountSerializer(read_only=True) class Meta: model = UserProfile fields = "__all__" def update(self, instance, validated_data): user_data = validated_data.pop('user', None) if user_data: account = instance.user # 仅更新基本信息字段,跳过密码相关 for field in ['first_name', 'last_name', 'email']: if field in user_data: setattr(account, field, user_data[field]) account.save() return super().update(instance, validated_data) # 若需支持创建UserProfile时同步创建Account,重写create方法 def create(self, validated_data): user_data = validated_data.pop('user') user = AccountSerializer(data=user_data).create(user_data) profile = UserProfile.objects.create(user=user, **validated_data) return profile
补充说明
- 如果需要在更新用户时支持修改密码,前端必须同时传入
password和confirm_password,方案1会自动验证匹配性并加密存储。 - 方案2更适合仅更新用户基本信息的场景,减少不必要的验证开销。
内容的提问来源于stack exchange,提问作者Sins97
相关产品推荐
相关产品推荐

