在管理站点中,我有一个自定义表单。但是,我想覆盖 save 方法,以便在输入某个关键字时,我不会将其保存到数据库中。这可能吗?
class MyCustomForm (forms.ModelForm):
def save(self, commit=True):
input_name = self.cleaned_data.get('input_name', None)
if input_name == "MyKeyword":
//Do not save
else:
return super(MyCustomForm, self).save(commit=commit)
但这会返回错误:
AttributeError 'NoneType' object has no attribute 'save'
编辑遵循此操作:覆盖 Django ModelForm 中的 save 方法
我试过了:
def save(self, force_insert=False, force_update=False, commit=True):
m = super(MyCustomCategoryForm, self).save(commit=False)
input_name = self.cleaned_data.get('input_name', None)
if input_name != "MyKeyword":
m.save()
return m
但是,如果input_name是"MyKeyword",则管理站点仍会创建一个新条目
save()
方法应该返回对象,无论是否保存。它应该看起来像:
def save(self, commit=True):
input_name = self.cleaned_data.get('input_name')
if input_name == "MyKeyword":
commit = False
return super().save(commit=commit)
但是,正如您在此处和此处看到的,该表单已经使用 commit=False
调用,并且稍后通过 ModelAdmin
的 save_model()
方法保存该对象。这就是你得到AttributeError 'NoneType' object has no attribute 'save'
的原因。如果您检查异常的回溯,我很确定错误来自这一行。
因此,此外,您还应该覆盖ModelAdmin
的save_model()
方法:
def save_model(self, request, obj, form, change):
if form.cleaned_data.get('input_name') == 'MyKeyword':
return # Don't save in this case
super().save_model(request, obj, form, change)
# And you'll also have to override the `ModelAdmin`'s `save_related()` method
# in the same flavor:
def save_related(self, request, form, formsets, change):
if form.cleaned_data.get('input_name') == 'MyKeyword':
return # Don't save in this case
super().save_related(request, form, formsets, change)
鉴于您在此答案中的评论
它现在正在工作,但我只有一个相关的问题。管理站点仍将在顶部显示绿色横幅,上面写着"模型已成功添加"。我可以覆盖某些方法,使其为红色并显示"模型已存在"吗?
看起来您要做的不是覆盖保存方法,而是控制表单验证。这是完全不同的。您只需要重写窗体的 clean 方法即可。
from django import forms
def clean(self):
"""
super().clean()
if self.cleaned_data.get('input_name') == 'MyKeyword':
raise forms.ValidationError("The model already exists")
或者,甚至更好,因为它看起来像您想要清理单个字段:
from django import form
def clean_input_name(self):
data = self.cleaned_data['input_name']
if data == 'MyKeyWord':
raise forms.ValidationError("The model already exists")
但是,我想input_name
也是您模型的一个字段,您不想仅在一个窗体上而是在所有项目中引发此错误。在这种情况下,您要查找的是模型验证器:
from django.core.exceptions import ValidationError
def validate_input_name(value):
if value == 'MyKeyword':
raise ValidationError("The model already exists")