I am using Wagtail CMS and I need some validation for my Orderable
model. Like, ensuring that at most one of the fields is filled.
Normally, I would override the clean(self)
method for the Django model, but calling super().clean()
inside that method returns None
. I am still able to access the fields with self.field_name
and raising ValidationError
still prevents the model from creation, but it doesn't show which fields caused the error for the model in the admin interface.
I have tried overriding the clean
method, that stops the model from being committed but doesn't show errors on the interface
I have tried following this part of the guide, but the clean
method there isn't even called for the Orderable
.
This is the example of my clean
method
def clean(self):
super().clean()
has_image = self.image is not None
has_video = self.video_url is not None
if has_image == has_video:
raise ValidationError('Either a video or an image must be set')
I expect validation errors to show up in the admin interface.
I've dug into the wagtail source code and I think I found the way of how to access the form controls for the orderable.
Let's say you have a model for a page,
class TestPage(Page):
testPageTitle = RichTextField(blank=True, max_length=250)
content_panels = Page.content_panels + [
FieldPanel('testPageTitle'),
InlinePanel('test_page_field')
]
base_form_class = TestPageForm
with some orderable model, that is linked to the page through a related name 'test_page_field',
class TestPageField(Orderable):
page = ParentalKey(TestPage, on_delete=models.CASCADE, related_name='test_page_field')
testPageFieldTitle = models.CharField(blank=True, max_length=250)
panels = [
FieldPanel('testPageFieldFieldTitle')
]
then you can access that within the clean method of the page, via self.formsets['test_page_field'].forms
, which is a list of Django form objects, where the regular checks can be done and .add_error()
method can be used. The relevant base_form_class
would look as follows:
class TestPageForm(WagtailAdminPageForm):
def clean(self):
cleaned_data = super().clean()
#loop over linked orderables
for form in self.formsets['test_page_field'].forms:
#check first if form is valid, otherwise cleaned_data will not be accesible/set
if form.is_valid():
cleaned_form_data = form.clean()
testPageFieldFieldTitle = cleaned_form_data.get('testPageFieldFieldTitle')
#execute some validation condition, and raise the error if it fails
if testPageFieldFieldTitle is None:
form.add_error('testPageFieldFieldTitle', 'please dont leave me empty')
return cleaned_data
I hope this helps.