在Django表单集中使用clean修改字段

4 投票
2 回答
4596 浏览
提问于 2025-04-18 00:30

如何在Django的表单集合中使用clean方法来修改每个表单的字段?

class MyInlineFormSet(BaseInlineFormSet):

    def clean(self):
        if self.cleaned_data['inputted'] == self.cleaned_data['answer']:
            self.cleaned_data['is_correct'] = True
        return self.cleaned_data

这个方法不太奏效,我看到有人遍历每个表单,但他们只是验证数据,并没有进行修改。如果我遍历每个表单,那我该如何返回cleaned_data呢?换句话说:

class MyInlineFormSet(BaseInlineFormSet):

    def clean(self):    
        for form in self.forms:
            if form.cleaned_data['inputted'] == form.cleaned_data['answer']:
                form.cleaned_data['is_correct'] = True
        ...?

2 个回答

0

我觉得你现在的做法是对的,你在逐个处理表单并设置清理后的数据(你第二个例子中的做法)。BaseFormSet 有一个叫做 cleaned_data 的属性,它会返回每个表单清理后的数据列表。这是你想要的吗?比如:

return self.cleaned_data

它实际上返回的是:

[form.cleaned_data for form in self.forms]

如果我理解代码没错的话,这里应该有正确的数据(经过修改的)。

如果你只是想把值保存到你的模型里,我建议你不要使用 clean 方法,而是重写 save 方法:

def save_new(self, form, commit=True):
    form.instance.is_correct = ...
    return super(...).save_new(...)

def save_existing(...)
2

根据ssomnoremac的评论,我在BaseModelFormSet的clean方法中使用了form.instance.field_i_wanted_to_change,而不是form.cleaned_data['field_i_wanted_to_change'],这样就成功了。大概是这样的:

class MyInlineFormSet(BaseInlineFormSet):

def clean(self):
    for form in self.forms:
        if form.cleaned_data['inputted'] == form.cleaned_data['answer']:
            form.instance.is_correct = True

在我的情况下,我已经调用了clean_field_i_wanted_to_change,所以顺序是先执行clean_field,然后是clean @ MyInlineFormSet。这个是在Django 1.11版本下的做法。

撰写回答