Django formset验证:自动修复表单验证错误

时间:2013-04-10 08:11:56

标签: django django-forms

在我的模型中,我有以下

--- models.py ---
class A(models.Model):
   my_Bs = models.ManyToManyField('B', through='AlinksB')
   ...

class B(models.Model):
   ...

class AlinksB(models.Model):
   my_A = models.ForeignKey(A)
   my_B = models.models.ForeignKey(B)
   order = models.IntegerField()

相应的管理员也是如此(管理员视图有内联链接B实例,我准备了自定义此内联的formset和表单所需的内容):

--- admin.py ---
class AlinksBInlineForm(forms.ModelForm):
   class Meta:
      model = AlinksB

class AlinksBInlineFormset(forms.models.BaseInlineFormSet): # there also is a BaseModelFormset
   form = AlinksBInlineForm

class AlinksBInline(admin.TabularInline):
   formset = AlinksBInlineFormset
   model = AlinksB

class AAdmin(admin.ModelAdmin):
   form = AForm
   inlines = (AlinksBInline,)
   ...

class BAdmin(admin.ModelAdmin):
   ...

现在要自定义表单验证,没什么困难:只需覆盖表单对象的“clean”方法。如果你想在formset中有许多不同的表单,我认为你只需要在formset的“ init ”方法中手动更改一些。但是,当我们清理formset时,以编程方式验证所有表单,以及仅在某些条件下才会这样做。

在我的情况下:如果所有订单(要排除的内联行)都为空,如何使用自动增量自动设置“订单”字段(在管理员视图的内联中)?!

1 个答案:

答案 0 :(得分:3)

我花了很多时间用Google搜索在Django Framework中进行表单集验证时尝试执行自动表单清理。几天之后,我无法找到解决方案,所以我开始关注Django的源代码,看看工作领域,小部件,表单和表单集。

以下是我的理解:

- 用户在提交存储在formset的“数据”属性中的formset时发布的所有数据。此属性非常难看,无法直接使用。 - 表单只是字段的包装器(它调用所有字段的干净方法并填充错误缓冲区,只有几个)

- 表单字段包含一个小部件。此窗口小部件允许从formset的“data”属性中返回字段的原始值

form.add_prefix('field name') # returns the 'field prefix', the key of formset.data used to retrieve the field's raw value
form.fields['field name'].widget.value_from_datadict(form.data, form.files, 'field prefix') # returns the raw value

- 表单字段还有一个方法可以将原始值转换为正确的python值(在我的例子中:order是一个整数,如果字段为空则为None)

form.fields['field name'].to_python(raw_value) # returns a value with the right type

- 您可以使用以下代码

更改formset中某个字段的值
form.data.__setitem__('field prefix', value) # code to update an iterable knowing the key to change

- 一旦修改了字段值,您可以调用表单的“ full_clean ”方法重试清除它们(这将删除以前的错误)。

- 一旦您再次验证了表单,您也可以使用“ full_clean ”方法重试验证表单集。但要注意避免无限循环

- 表单干净数据只能使用只读数据,在表单或formset中添加更多错误消息

另一种解决方案是手动更改“form.clean_data”属性,并清除formset.errors和所有form.errors

希望它可以帮助处理与我相同情况的人!

Ricola3D