【问题标题】:Django Formset Missing Management Form DataDjango Formset 缺少管理表单数据
【发布时间】:2018-03-30 18:10:03
【问题描述】:

我正在尝试为表单集编写单元测试,但在尝试实例化它时遇到以下错误。

错误:

Traceback (most recent call last):
    File "/home/jwelborn/Documents/projects/Bingo/bingo/cards/tests/test_forms.py", line 218, in test_formset_accepts_valid_data
        self.assertTrue(formset.is_valid())
    File "/home/jwelborn/Documents/projects/Bingo/bingoenv/lib/python3.6/site-packages/django/forms/formsets.py", line 321, in is_valid
        self.errors
    File "/home/jwelborn/Documents/projects/Bingo/bingoenv/lib/python3.6/site-packages/django/forms/formsets.py", line 295, in errors
        self.full_clean()
    File "/home/jwelborn/Documents/projects/Bingo/bingoenv/lib/python3.6/site-packages/django/forms/formsets.py", line 343, in full_clean
        for i in range(0, self.total_form_count()):
    File "/home/jwelborn/Documents/projects/Bingo/bingoenv/lib/python3.6/site-packages/django/forms/formsets.py", line 116, in total_form_count
        return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max)
    File "/home/jwelborn/Documents/projects/Bingo/bingoenv/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
        res = instance.__dict__[self.name] = self.func(instance)
    File "/home/jwelborn/Documents/projects/Bingo/bingoenv/lib/python3.6/site-packages/django/forms/formsets.py", line 98, in management_form
        code='missing_management_form',
    django.core.exceptions.ValidationError: ['ManagementForm data is missing or has been tampered with']

此错误表明我缺少 ManagmentForm 数据,但我将其包含在要传递给表单的字典中。我检查了不同的拼写并改变了最小和最大数字,但无济于事。

forms.py:

class BingoSquareForm(ModelForm):

    class Meta:
        model = BingoCardSquare
        exclude = ('created_date',)


BingoSquareFormset = inlineformset_factory(
    BingoCard,
    BingoCardSquare,
    form=BingoSquareForm,
    min_num=24,
    validate_min=True,
    max_num=24,
    validate_max=True
)

tests.py

class BingoSquareFormsetTests(TestCase):

    def setUp(self):

        self.user = User.objects.get_or_create(
            username='FormsetTestUser',
            email='something@yahoo.org'
        )[0]
        self.user.set_password('bingo')
        self.user.save()

        self.card = BingoCard.objects.get_or_create(
            title='FormsetTest',
            free_space='free_space',
            creator=self.user,
        )[0]

        self.data = {
            'form-TOTAL_FORMS': '24',
            'form-INITIAL_FORMS': '0',
            'form-MAX_NUM_FORMS': '24',
            'form-MIN_NUM_FORMS': '24'
        }

        for i in range(24):
            text_key = 'form-{}-text'.format(i)
            text_value = 'square {}'.format(i)
            self.data[text_key] = text_value

    def test_formset_accepts_valid_data(self):

        formset = BingoSquareFormset(self.data)
        self.assertTrue(formset.is_valid())

谁能看出我做错了什么?

【问题讨论】:

    标签: python django unit-testing testing


    【解决方案1】:

    这个错误是由于没有为表单集的表单数据使用正确的前缀。 Django 的inlineformset_factory 自动将formset 前缀设置为子模型的 ForeignKeyField 中定义的related_name

    models.py:

    class BingoCardSquare(models.Model):
    
        ...
    
        card = models.ForeignKey(
            BingoCard,
            related_name='squares',
            on_delete=models.CASCADE,
        )
        ...
    

    在这种情况下,self.data 属性应设置为以下内容:

    self.data = {
        'squares-TOTAL_FORMS': '24',
        'squares-INITIAL_FORMS': '0',
        'squares-MAX_NUM_FORMS': '24',
        'squares-MIN_NUM_FORMS': '24'
        }
    

    每个附加表单都需要以相同的方式添加前缀。希望这个答案能帮助未来陷入困境的 djangonaut。

    【讨论】:

    • 另见docs: "BookFormSet的前缀是'book_set' (<model name>_set)。如果BookForeignKeyAuthor有一个related_name,而是使用它。”这是指BookFormSet = inlineformset_factory(parent_model=Author, model=Book, ...))。
    猜你喜欢
    • 1970-01-01
    • 2011-02-01
    • 2021-07-13
    • 2011-11-06
    • 2018-11-09
    • 2011-07-29
    • 2011-06-23
    • 2015-07-09
    • 1970-01-01
    相关资源
    最近更新 更多