I am trying to make a page with Wagtail CMS that validates the content whenever I save/publish the page inside the admin editor.
The content that I want to be validated is the content of 3 SnippetChooserPanels from within the page. Basically let's say I have these 3 snippets : SnippetA, SnippetB and SnippetC and these snippets (or Django models because that's what they really are) have the following relationships:
- SnippetA has one to many relationship with SnippetB
- SnippetB has one to many relationship with SnippetC.
When the user saves/publishes the page I want to verify:
- that all the 3 snippet types have been chosen
- that there is a correct relationship between the snippets (ie SnippetC belongs to SnippetB , and SnippetB belongs to SnippetsA, or in other words the 3 snippets are joined together correctly in SQL database terms)
Thank you!
CodePudding user response:
Wagtail allows you to customise the editing form for each of your Page
models via the base_form_class
attribute on your Page
model.
The class that this references must be one that subclasses WagtailAdminPageForm
. This is a Django Form
at its core and hence has a clean
method that allows additional custom validation on submission along with failing the save step and providing per field error messages.
Docs
- Wagtail - customising the editing interface
- Django - Form and field validation
Code Example models.py
from django import forms
from django.db import models
from wagtail.admin.edit_handlers import FieldPanel
from wagtail.admin.forms import WagtailAdminPageForm
from wagtail.core.models import Page
from wagtail.snippets.edit_handlers import SnippetChooserPanel
class CustomPageForm(WagtailAdminPageForm):
def clean(self):
cleaned_data = super().clean()
# Make sure that the the snippets relate to each other correctly
snippet_a = cleaned_data['snippet_a']
snippet_b = cleaned_data['snippet_b']
snippet_c = cleaned_data['snippet_c']
# example validation only - you will need to work this out based on your exact requirements
if snippet_a.pk is snippet_b.pk:
self.add_error('snippet_a', 'The snippets must be different')
if snippet_b.pk is snippet_c.pk:
self.add_error('snippet_a', 'The snippets must be different')
if snippet_c.pk is snippet_a.pk:
self.add_error('snippet_a', 'The snippets must be different')
if snippet_c.pk is snippet_b.pk:
self.add_error('snippet_a', 'The snippets must be different')
return cleaned_data
class EventPage(Page):
# note: actual models.ForeignKey usage not added, just for the example
snippet_a = models.ForeignKey()
snippet_b = models.ForeignKey()
snippet_c = models.ForeignKey()
content_panels = [
SnippetChooserPanel('snippet_a'),
SnippetChooserPanel('snippet_b'),
SnippetChooserPanel('snippet_c'),
]
base_form_class = CustomPageForm