How to validate a Django form based on Parent and Child form fields?

Viewed 113

I have this structure, in Django 2.2:

# models.py
class Child(models.Model):
    parent2 = models.ForeignKey(Parent_2, on_delete=models.SET_NULL, null=True)
    parent = models.ForeignKey(Parent_1, on_delete=models.CASCADE, null=True)
    name = models.CharField('Name')

class Parent_1(models.Model):
    cost = models.DecimalField('Cost', max_digits=6, decimal_places=2)
    date = models.DateField('Date', default=datetime.date.today)

    def __init__(self, *args, **kwargs):
        super(Parent_1, self).__init__(*args, **kwargs)
        self.__formset_is_valid__ = None

# admin.py
class ChildInline(admin.TabularInline):
    model = Child
    form = ChildInlineForm

class Parent_1Admin(admin.ModelAdmin):
    inlines = [ChildInline]
    form = Parent_1AdminForm

# form.py
class ChildInlineForm(forms.ModelForm):
    class Meta:
        model = Child

    def clean(self):
        cleaned_data = super(ChildInlineForm, self).clean()
        self.instance.__formset_is_valid__ = self.is_valid()
        # print(self.instance.__formset_is_valid__)

class Parent_1AdminForm(forms.ModelForm):
    extra_field = forms.CharField(widget=forms.Textarea(attrs={'rows': 10}))
    extra_field.required = False
    class Meta:
        model = Parent_1

    def clean(self):
        cleaned_data = super(Parent_1AdminForm, self).clean()

        fields_warning = "Please fill 'extra_field' OR ChildInlineForm"

        if self.has_changed():
            extra_field_cleaned = cleaned_data.get("extra_field")

            if not extra_field_cleaned and (self.instance.__formset_is_valid__ is not True):
                self.add_error("extra_field", ValidationError(fields_warning, code='%s-extra_field' % self.prefix))

        return cleaned_data

I based the code above on this answer to realize a chained validation between Parent1 form and Child Form. I would like a user can fill the extra_field OR at least a formset to have a valid form, but using the logic above:

  • if I fill extra_field field the form is valid and content is saved
  • if I fill the child form, parent form is not valid because it already has self.__formset_is_valid__ = None I suppose.

How can I fix my code to achieve my goal?

0 Answers
Related