测试 InlineFormset 清理方法

Posted

技术标签:

【中文标题】测试 InlineFormset 清理方法【英文标题】:Testing InlineFormset clean methods 【发布时间】:2012-11-09 14:46:03 【问题描述】:

我有一个 Django 项目,有 2 个模型,StructureBracket,括号有一个结构的外键(即一对多,一个结构有很多括号)。我为管理站点创建了一个TabularInline,这样结构上就会有一个括号表。我添加了一个自定义表单集,其中包含一些自定义 clean 方法来做一些额外的验证,你不能有一个与同一结构上的另一个括号冲突的括号等。

管理员是这样的:

class BracketInline(admin.TabularInline):
    model = Bracket
    formset = BracketInlineFormset

class StructureAdmin(admin.ModelAdmin):
    inlines = [
        BracketInline
    ]
admin.site.register(Structure, StructureAdmin)

BracketInlineFormset 只是有 clean 方法:

class BracketInlineFormset(forms.models.BaseInlineFormSet):
    def clean(self):
        … my clean code here …

一切正常,验证正常。

但是现在我想编写一些单元测试来测试我复杂的表单集验证逻辑。

我第一次尝试验证已知良好值是:

data = 'form-TOTAL_FORMS': '1', 'form-INITIAL_FORMS': '0', 'form-MAX_NUM_FORMS': '', 'form-0-field1':'good-value', … 
formset = BracketInlineFormset(data)
self.assertTrue(formset.is_valid())

但这不起作用并引发异常:

======================================================================
ERROR: testValid (appname.tests.StructureTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/paht/to/project/tests.py", line 494, in testValid
    formset = BracketInlineFormset(data)
  File "/path/to/django/forms/models.py", line 672, in __init__
    self.instance = self.fk.rel.to()
AttributeError: 'BracketInlineFormset' object has no attribute 'fk'

----------------------------------------------------------------------

Django documentation(用于表单集验证)意味着可以做到这一点。

这怎么行不通?如何测试我的内联表单集的自定义 clean()/validation?

【问题讨论】:

BracketInlineFormset 的声明是什么样的? @JohnMee 内联表单集代码添加到问题 【参考方案1】:

您可以使用 django.forms.models 中的 inlineformset_factory 方法来创建自定义的内联表单集。此方法根据传递给它的父类将 fk 值设置为您的表单集。

structure = StructureFactory() #foreign key
data = 'form-TOTAL_FORMS': '1', 'form-INITIAL_FORMS': '0', 'form-MAX_NUM_FORMS': '', 'form-0-field1':'good-value', … 
BIFormset = inlineformset_factory(Structure, Bracket, formset=BracketInlineFormset)
formset = BIFormset(data, prefix='form', instance=structure) 
self.assertTrue(formset.is_valid())

使用工厂构造表单集时注意formset=BracketInlineFormset参数。

参考:Django Docs

【讨论】:

以上是关于测试 InlineFormset 清理方法的主要内容,如果未能解决你的问题,请参考以下文章

Django - 修改Inlineformset删除按钮

具有一个模型和 inlineformset 的 Formwizard

django - 具有多个 ForeignKey 的 inlineformset_factory

formset、inlineformset_Factory 和 kwargs

Think in Java:初始化与清理

在 Django inlineformset_factory 中过滤查询集