Home > OS >  Wagtail CMS how to validate the content of one page before publishing or saving it as draft
Wagtail CMS how to validate the content of one page before publishing or saving it as draft

Time:10-06

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

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
  • Related