4

In Django you can add a clean method to a form to validate fields that depend on each other:

def clean_recipients(self):
    data = self.cleaned_data['recipients']
    if "fred@example.com" not in data:
        raise ValidationError("You have forgotten about Fred!")

    # Always return a value to use as the new cleaned data, even if
    # this method didn't change it.
    return data

How can I add a custom form with a clean method to Wagtail ModelAdmin?

Wagtail has the panels concept and dynamically builds the form. I can't find anything about overriding the form. There is information about customising the create and update views. Custom views seem a bit cumbersome.

allcaps
  • 10,945
  • 1
  • 33
  • 54

1 Answers1

4

I got an answer via the Wagtail Slack form @CynthiaKiser.

The base_form_class lets you set a WagtailAdminModelForm on the model.

from wagtail.admin.forms import WagtailAdminModelForm

class Foo(models.Model):
    ...
    base_form_class = FooForm


class FooForm(WagtailAdminModelForm):  # For pages use WagtailAdminPageForm
    def clean(self):
        data = self.cleaned_data['recipients']
        if "fred@example.com" not in data:
            raise ValidationError("You have forgotten about Fred!")
        return data

All of the CRUD forms you encounter in Wagtail are just Django ModelForm instances underneath, so these Django docs are relevant (thanks @ababic)

An alternative to base_form_class is to specify a clean method on the model. It will be called by any form.

from django.core.exceptions import ValidationError

class Foo(models.Model):
    ...
    def clean(self):
        if "fred@example.com" not in self.recipients:
            raise ValidationError(
                {'recipients': _("You have forgotten about Fred!")}
            )
allcaps
  • 10,945
  • 1
  • 33
  • 54
  • With noting that all of the CRUD forms you encounter in Wagtail are just Django ModelForm instances underneath, so these Django docs are relevant: https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects – ababic Aug 10 '21 at 06:34
  • Just a note here because this tripped me up for a bit: you should use the appropriate Wagtail base form for the model you're working with. If you're inheriting from `Page` instead of `models.Model` you'd import `WagtailAdminPageForm` instead of `WagtailAdminModelForm` – Peter Jun 18 '22 at 20:09