如何在ModelForm的clean方法中获取Article实例及原有字段值?
嘿,我来帮你理清这个问题!你遇到的self.instance看起来是None的情况,其实是因为你当前的代码场景是创建新的Article实例,而非编辑已有实例,咱们一步步拆解:
为什么你看到self.instance是“None”?
你当前的视图代码里,初始化表单时只传了提交的数据:
form = ArticleForm({'name':'test', 'value':'test'})
这时候self.instance并不是真的None,而是一个还没保存到数据库的空Article实例——你打印时看到的None其实是这个实例的主键(pk)值,因为新实例还没入库,主键还没生成。
分场景解决你的需求
场景1:创建新的Article实例
如果是要新增数据,你其实不需要“原有值”(本来就没有),但如果想获取表单提交的新值,有两种方式:
- 从
cleaned_data里直接拿(推荐) - 访问
self.instance的字段(因为表单已经把提交的数据填充到实例里了)
修改你的表单clean方法试试:
def clean(self): cleaned_data = super().clean() # 方式1:从cleaned_data取新值 new_name = cleaned_data.get('name') new_value = cleaned_data.get('value') # 方式2:从self.instance取(此时实例已被表单填充数据) print(self.instance.name) # 会输出'test' print(self.instance.pk) # 输出None,因为还没保存到数据库 return cleaned_data
场景2:编辑已有的Article实例
如果是要修改数据库里已存在的文章,你必须在初始化表单时传入instance参数,这样self.instance才会指向数据库里的原有实例,你就能拿到旧值了。
修正后的视图代码:
def test(request): # 先从数据库取出要编辑的实例(比如pk=1的文章) article = Article.objects.get(pk=1) # 初始化表单时,同时传入instance和提交的数据 form = ArticleForm({'name':'new_test', 'value':'new_test'}, instance=article) if form.is_valid(): form.save() # 把修改保存到数据库 print("修改成功!") else: print(form.errors)
表单里获取原有值:
def clean(self): cleaned_data = super().clean() instance = self.instance # 先判断是不是编辑场景(实例已经有主键,说明存在于数据库) if instance.pk is not None: # 获取数据库里的原有值 original_name = instance.name original_value = instance.value print(f"原来的名称:{original_name},原来的值:{original_value}") # 获取新提交的值 new_name = cleaned_data.get('name') print(f"新提交的名称:{new_name}") # 比如可以加个校验:新名称不能和旧的一样 if new_name == original_name: raise forms.ValidationError("名称不能和原来的一模一样哦!") return cleaned_data
内容的提问来源于stack exchange,提问作者Denis Azi
相关产品推荐
相关产品推荐

