0

在我的模型中,我有以下内容

--- 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 实例,我准备了自定义此内联的表单集和表单所需的内容):

--- 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):
   ...

现在自定义表单验证,没什么难的:只需覆盖表单对象的“干净”方法。如果您想在表单集中使用许多不同的表单,我认为您只需在表单集的“ init ”方法中手动更改一些。但是,当我们清理表单集时,以编程方式验证所有表单怎么样,并且仅在某些条件下。

就我而言:如果所有订单(要删除排除的内联行)为空,如何自动设置“订单”字段(在管理视图的内联中)并自动增加?!

4

1 回答 1

3

我刚刚花了很多时间在谷歌上搜索尝试在 Django 框架中的表单集验证期间执行自动表单清理。几天后,我想不出一个解决方案,所以我开始直接查看 Django 的源代码,看看字段、小部件、表单和表单集是如何工作的。

这是我的理解:

- 用户提交表单集时发布的所有数据,它存储在表单集的“数据”属性中。这个属性很丑,不能直接使用。- 表单只是字段的包装器(它调用所有字段的干净方法并填充错误缓冲区,仅此而已)

- 表单域有一个小部件。这个小部件允许从表单集的“数据”属性中取回字段的原始值

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

- 您可以使用以下代码更改表单集中其中一个字段的值

form.data.__setitem__('field prefix', value) # code to update an iterable knowing the key to change

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

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

- 表单清理数据只能使用只读数据,在表单或表单集中添加更多错误信息

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

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

Ricola3D

于 2013-04-10T08:11:56.427 回答