Ветвление рабочих процессов на основе значения указанного поля Page
 У меня есть модель DailyReflectionPage с полем reflection_date, которое формирует основу для slug страницы, имеющего форму YYYY-MM-DD. Вот выдержка из моей модели Page:
class DailyReflectionPage(Page):
    """
    The Daily Reflection Model
    """
    ...
    ...
    reflection_date = models.DateField("Reflection Date", max_length=254)
    ...
    ...
    @cached_property
    def date(self):
        """
        Returns the Reflection's date as a string in %Y-%m-%d format
        """
        fmt = "%Y-%m-%d"
        date_as_string = (self.reflection_date).strftime(fmt)
        return date_as_string      
    ...
    ...
    def full_clean(self, *args, **kwargs):
        # first call the built-in cleanups (including default slug generation)
        super(DailyReflectionPage, self).full_clean(*args, **kwargs)
        # now make your additional modifications
        if self.slug is not self.date:
            self.slug = self.date
    ...
    ...
Эти ежедневные размышления пишутся разными авторами в рамках буклета, который публикуется в конце года и предназначен для использования в следующем году. Я бы хотел, чтобы рабочий процесс, например, ежедневные размышления с января по июнь рассматривались одной группой, а с июля по декабрь - другой, как показано на схеме ниже:
Как этого можно достичь?
 Этого можно достичь, создав ОДИН новый тип рабочего процесса Task, который имеет отношение к двум наборам пользователей Group (например, a/b или before/after, вероятно, лучше оставить это общим в определении модели).
Этот новый Task может быть создан как часть нового Workflow в админке Wagtail, и каждая из групп, связанных с группой модератора 1 / 2.
 Методы Wagtail на Task позволяют возвращать варианты утверждения на основе модели Page для любого созданного рабочего процесса, отсюда вы можете искать метод, который был бы на классе, и назначать группы оттуда.
Преимущества более общего подхода в том, что вы можете использовать его для любого разделения заданий модераторов в рамках будущих задач Workflow.
Обзор внедрения
- 1 - прочитайте Wagatail Docs о том, как добавить новый тип задачи и 
Taskmodel reference, чтобы понять этот процесс. - 2 - Прочитайте полную реализацию в коде встроенного 
GroupApprovalTask. - 3 - В 
GroupApprovalTaskвы можете увидеть, что методы с переопределениями все полагаются на проверкуself.groups, но все они получаютpage, переданные в качестве аргумента этим методам. - 4 - Создайте новую модель 
Task, расширяющую класс WagtailTaskи на этой модели создайте две моделиManyToManyField, позволяющие связать два набора групп пользователей (примечание: не обязательно делать это в виде двух полей, можно поместить модель в середину, но приведенный ниже пример - это просто простейший способ добраться до гала). - 5 - На модели 
DailyReflectionPageсоздайте методget_approval_group_key, который будет возвращать, возможно, простое булево или 'A' или 'B' на основе бизнес-требований, описанных вами выше (проверка даты модели и т.д.) - 6 - В вашем пользовательском 
Taskсоздайте метод, который абстрагирует проверкуPageдля этого метода и возвращает группу пользователей Задачи. Возможно, вы захотите добавить некоторую обработку ошибок и значения по умолчанию. Например,get_approval_groups.
 - 7 - Добавьте пользовательский метод для каждого из методов 'start', 'user_can_access_editor', 
page_locked_for_user,user_can_lock,user_can_unlock,get_task_states_user_can_moderate, который вызываетget_approval_groupсо страницей и возвращает значения (см. кодGroupApprovalTaskдля того, что они должны делать. ).
 
Примеры фрагментов кода
models.py
class DailyReflectionPage(Page):
    """
    The Daily Reflection Model
    """
    def get_approval_group_key(self):
        # custom logic here that checks all the date stuff
        if date_is_after_foo:
            return 'A'
        return 'B'    
class SplitGroupApprovalTask(Task):
    ## note: this is the simplest approach, two fields of linked groups, you could further refine this approach as needed.
    groups_a = models.ManyToManyField(
        Group,
        help_text="Pages at this step in a workflow will be moderated or approved by these groups of users",
        related_name="split_task_group_a",
    )
    groups_b = models.ManyToManyField(
        Group,
        help_text="Pages at this step in a workflow will be moderated or approved by these groups of users",
        related_name="split_task_group_b",
    )
    admin_form_fields = Task.admin_form_fields + ["groups_a", "groups_b"]
    admin_form_widgets = {
        "groups_a": forms.CheckboxSelectMultiple,
        "groups_b": forms.CheckboxSelectMultiple,
    }
    def get_approval_groups(self, page):
       """This method gets used by all checks when determining what group to allow/assign this Task to"""
        
        # recommend some checks here, what if `get_approval_group` is not on the Page?
        approval_group = page.specific.get_approval_group_key()
        if (approval_group == 'A'):
            return self.group_a
        return self.group_b
    # each of the following methods will need to be implemented, all checking for the correct groups for the Page when called
    # def start(self, ...etc)
    # def user_can_access_editor(self, ...etc)
    # def page_locked_for_user(self, ...etc)
    # def user_can_lock(self, ...etc)
    # def user_can_unlock(self, ...etc)
    # def get_task_states_user_can_moderate(self, ...etc)
    def get_actions(self, page, user):
        # essentially a copy of this method on `GroupApprovalTask` but with the ability to have a dynamic 'group' returned.
        approval_groups = self.get_approval_groups(page)
        if approval_groups.filter(id__in=user.groups.all()).exists() or user.is_superuser:
            return [
                ('reject', "Request changes", True),
                ('approve', "Approve", False),
                ('approve', "Approve with comment", True),
            ]
        return super().get_actions(page, user)
                    