Django 4.0.3 Admin表单如何覆盖字段值并正确保存Cognito返回sub
问题原因
你代码里cognito_sub存不进库的核心原因是赋值写错了对象:你执行self.cognito_sub = sub时,是给表单类实例新增了一个普通属性,根本没有把值赋给表单绑定的BuyerUser模型实例。调用父类save()方法时,框架只会读取模型实例上的字段值落库,自然拿不到你生成的sub值。
就算你把cognito_sub加到exclude列表里,框架只会跳过从表单提交数据读取该字段的步骤,你没手动给模型实例赋值的话,存库的永远是空值。
另外你在save方法里手动给self.given_name、self.email等属性赋值的操作完全无效,这些属性挂在表单实例上,不会同步到模型实例。
正确实现
直接删掉你自定义的__init__方法,重写save方法时先拿到模型实例,把生成的sub值赋给实例字段后再落库,修改后的BuyerUserAddForm代码如下:
class BuyerUserAddForm(forms.ModelForm): grupo = forms.CharField(label="Cognito用户分组") def save(self, commit=True): # 先构造未持久化的模型实例,此时表单提交的合法字段值已经自动赋给实例 user_instance = super().save(commit=False) # 调用Cognito接口创建用户 cognito_client = CognitoDriver() cognito_user_data = cognito_client.create_user( user_instance.preferred_username, user_instance.email ) sub_value = cognito_client.parse_user(cognito_user_data["User"])["Sub"] # 核心:给模型实例的cognito_sub字段赋值 user_instance.cognito_sub = sub_value # 配置Cognito用户分组 grupo_val = self.cleaned_data.get("grupo") if grupo_val: cognito_client.add_group(user_instance.preferred_username, grupo_val) # 按commit参数决定是否落库 if commit: user_instance.save() self.save_m2m() return user_instance class Meta: model = BuyerUser # 排除不需要在新建表单展示的字段,cognito_sub由接口自动生成,不允许管理员手动填写 exclude = ['terms_conditions_accepted_datetime', 'cognito_sub']
补充说明
- 编辑用户使用的
BuyerUserChangeForm不需要额外修改,如果不希望管理员在编辑页修改已生成的cognito_sub,也可以把该字段加到ChangeForm的exclude列表里,避免误操作。 - 建议给Cognito接口调用逻辑加异常捕获,当Cognito用户创建失败时直接抛出表单校验错误,避免Django侧生成无对应Cognito账号的脏数据。
- 不重写模型save方法处理这段逻辑的思路是对的,
grupo是仅表单使用的临时字段,放在Form层处理耦合度更低。
内容的提问来源于stack exchange,提问作者fils capo
相关产品推荐
相关产品推荐

