我有BaseInlineFormSet
,我想根据子项字段的值验证父表单中的字段。如the docs所示,进行自定义验证的唯一方法是clean()
,但我找不到向父表单添加错误的方法,仅针对子项。
在下面的代码中,我构建了一个公式。每个变量都来自内部表单,如果全局公式未经验证,我想在父表单字段formula
class CustomInlineFormSet(BaseInlineFormSet):
def clean(self):
formula = self.instance.formula
variables = []
for form in self.forms:
if 'formula_variable' in form.cleaned_data:
variables.append(form.cleaned_data['formula_variable'])
valid, msg = validate_formula(formula, variables)
if not valid:
WHAT HERE???
答案 0 :(得分:3)
看看这些链接:
和
但似乎要点是:
ModelAdmin
ModelForm
有一个干净的方法来执行主Model
实例的验证ModelAdmin
可以访问InlineFormset
s(https://github.com/django/django/blob/master/django/contrib/admin/options.py#L530)ModelForm
无权访问ModelAdmin
或ModelAdmin
的表单集(因此,它的干净方法无法交叉验证内联)BaseModelFormSet
(BaseInlineFormSet
扩展BaseModelFormSet
)有clean
方法(请参阅https://github.com/django/django/blob/master/django/forms/models.py#L635),但无法以任何方式访问主Model
实例所以你需要做的就是使用前两个链接作为指导。
答案 1 :(得分:0)
感谢Russell Keith-Magee,我设法解决了这个问题。我在这里详细说明答案以供将来参考。
我做错了,InlineFormSet不是我需要的那种验证的正确位置,它应该在父模型中完成。但是父ModelForm无法访问子FormSet,所以我只需要将FormSet作为参数传递给ModelForm。所以事情现在看起来像这样:
观点:
class FormulaCreate(CreateView):
model = Formula
template_name = "whatever.html"
def get_context_data(self, **kwargs):
context = super(ParameterRatioCreate, self).get_context_data(**kwargs)
if self.request.POST:
formset = FormulaVariablesFormSet(self.request.POST, instance=self.object)
context['form'] = FormulaForm(formset=formset, data=self.request.POST, instance=self.object)
context['formset'] = formset
else:
formset = FormulaVariablesFormSet(instance=self.object)
context['form'] = FormulaForm(formset=formset, instance=self.object)
context['formset'] = formset
return context
def form_valid(self, form):
context = self.get_context_data()
form = context['form']
formset = context['formset']
if form.is_valid() and formset.is_valid():
ratio = form.save()
formset = FormulaVariablesFormSet(self.request.POST, instance=ratio)
if formset.is_valid():
formset.save()
self.object = ratio
return redirect(self.get_success_url())
context['formset'] = formset
return self.render_to_response(context)
表格:
class FormulaForm(forms.ModelForm):
class Meta:
model = Formula
def __init__(self, formset, *args, **kwargs):
self.formset = formset
super(FormulaForm, self).__init__(*args, **kwargs)
def clean(self):
variables = {}
for form in self.formset:
if form.is_valid() and 'formula_variable' in form.cleaned_data:
variables[form.cleaned_data['formula_variable']] = 1
if 'formula' in self.cleaned_data:
formula = self.cleaned_data['formula']
valid, msg = do_formula(formula, variables)
if not valid:
self._errors['formula'] = self.error_class([msg])
del self.cleaned_data['formula']
return self.cleaned_data
FormSet:
FormulaVariablesFormSet = inlineformset_factory(Formula,
FormulaVariable,
extra=1)