CMS Wagtail как проверить содержимое одной страницы перед публикацией или сохранением ее в качестве черновика

#python #django #content-management-system #wagtail

Вопрос:

Я пытаюсь создать страницу с помощью CMS Wagtail, которая проверяет содержимое всякий раз, когда я сохраняю/публикую страницу в редакторе администратора.

Содержимое, которое я хочу проверить, — это содержимое 3 фрагментов страниц на странице. В принципе, допустим, у меня есть эти 3 фрагмента : фрагмент, ФрагменТ B и фрагмент C, и эти фрагменты (или модели Django, потому что это то, чем они на самом деле являются) имеют следующие отношения:

  • СниппетА имеет отношение один ко многим с сниппетом B
  • SnippetB имеет отношение один ко многим с SnippetC.

Когда пользователь сохраняет/публикует страницу, которую я хочу проверить:

  • что все 3 типа фрагментов были выбраны
  • что существует правильная взаимосвязь между фрагментами (т. е. Фрагмент C принадлежит фрагменту B , а фрагмент B принадлежит фрагменту A, или, другими словами, 3 фрагмента правильно объединены в терминах базы данных SQL)

Спасибо!

Ответ №1:

Трясогузка позволяет настроить форму редактирования для каждой из ваших Page моделей с помощью base_form_class атрибута в вашей Page модели.

Класс, на который ссылается это, должен быть подклассом WagtailAdminPageForm . Это Django Form по своей сути и, следовательно, имеет clean метод, который позволяет проводить дополнительную пользовательскую проверку при отправке, а также не выполнять шаг сохранения и предоставлять сообщения об ошибках для каждого поля.

Документы

Пример кода 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
 

Комментарии:

1. Да, похоже, это то, что я искал. Спасибо!

2. Эй, ЛБ, есть ли причина, по которой в этом случае не сработало бы просто переопределить clean() метод в самой EventPage модели? Необходимо ли использовать пользовательскую форму?

3. Эй, @ScottCranfill — хорошая мысль, я думаю, что это может сработать таким образом, я просто скопировал/вставил пример документов. Я думаю, что пример с документами также предназначался для добавления поля. не стесняйтесь редактировать этот ответ, если хотите.