Вопрос

I've added some validation to an inline in the django admin, which won't let the inline be saved if a field on the model instance doesn't exist. I don't want additional deadlines to be added if there isn't a deadline already:

class DeadlineInlineFormset(forms.models.BaseInlineFormSet):
    def clean(self):
        super(DeadlineInlineFormset, self).clean()
        # make sure deadline is set
        if not self.instance.deadline:
            raise ValidationError(_("Doesn't validate"))


class DeadlineInline(admin.StackedInline):
    model = AdditionalDeadline
    formset = DeadlineInlineFormset


class GrantAdmin(admin.ModelAdmin):
    ...
    inlines = [DeadlineInline]
    ...

This works fine but I'm struggling to unit test it. So far I have:

class GrantAdminTestCase(TestCase):

    fixtures = [...]

    def test_forms(self):
        # create the form from a model instance.
        # it should validate but it doesn't
        g = Grant.objects.first()
        form = GrantAdminForm(instance=g)
        self.assertEqual(form.is_valid(), True)

        # remove deadline and add additional deadlines
        # It shouldn't be valid because deadline is None
        g.deadline = None
        g.additional_deadlines.add(
            Deadline(deadline=datetime.now())
        )
        self.assertEqual(form.is_valid(), False)

The first assert fails even though the model instance is valid. The second assert passes but shouldn't because it now should be invalid. So something is definitely wrong.

I'm also not sure if this is the right way to do it at all. Would it be easier to put validation in the model? Or even in the form rather than the formset?

Edit: Quite a lot of this was wrong, I've changed a few things but it's still not working:

def test_forms(self):
    g = Grant.objects.first()
    form = GrantAdminForm(model_to_dict(g))
    self.assertEqual(form.is_valid(), True)

    DeadlineFormSet = inlineformset_factory(Grant, Deadline)

    # should be invalid
    g.deadline = None
    g.additional_deadlines.add(Deadline(deadline=datetime.now()))
    formset = DeadlineFormSet(instance=g)
    self.assertEqual(formset.is_valid(), False)

    # should be valid
    g = Grant.objects.first()
    formset = DeadlineFormSet(instance=g)
    self.assertEqual(formset.is_valid(), True)

The first two assertions pass but the last doesn't.

Это было полезно?

Решение

This led me to the answer which was:

class GrantAdminTestCase(TestCase):
    fixtures = [
        'grants/grant_config',
        'grants/grants',
    ]

    def setUp(self):
        self.g = Grant.objects.first()

        self.DeadlineFormSet = inlineformset_factory(
            Grant, Deadline, formset=DeadlineInlineFormset)

        self.data = {
            'additional_deadlines-INITIAL_FORMS': 0,
            'additional_deadlines-MAX_NUM_FORMS': 1000,
            'additional_deadlines-TOTAL_FORMS': 1,
            'additional_deadlines-0-deadline': date.today(),
            'additional_deadlines-0-grant': '2',
            'additional_deadlines-0-id': '',
        }

    def test_formset_is_valid_if_deadline_exists(self):
        formset = self.DeadlineFormSet(self.data, instance=self.g)
        self.assertEqual(formset.is_valid(), True)

    def test_formset_is_invalid_if_deadline_doesnt_exist(self):
        # formset should be invalid if there is an additional deadline
        # and no main deadline
        self.g.deadline = None
        formset = self.DeadlineFormSet(self.data, instance=self.g)
        self.assertEqual(formset.is_valid(), False)

    def test_formset_is_valid_if_deadline_blank(self):
        # formset should still be valid if deadline is blank
        # (it's not saved)
        self.data['additional_deadlines-0-deadline'] = ''
        formset = self.DeadlineFormSet(self.data, instance=self.g)
        self.assertEqual(formset.is_valid(), True)

    def test_formset_is_invalid_if_additional_deadlines_earlier(self):
        # formset should be invalid if any additional deadlines are earlier
        # than the main deadline
        self.g.deadline = date.today()
        yesterday = date.today() - timedelta(days=1)
        self.data['additional_deadlines-0-deadline'] = yesterday
        formset = self.DeadlineFormSet(self.data, instance=self.g)
        self.assertEqual(formset.is_valid(), False)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top