0

我有一个DailyReflectionPage模型,其reflection_date字段构成 Page 的 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
    ...
    ...

这些每日反思由不同的作者撰写,作为年底出版的小册子的一部分,以供来年使用。我想要一个工作流程,例如,从 1 月到 6 月的日常反思由一个小组审核,而从 7 月到 12 月的日常反思由另一个小组审核,如下图所示:

基于日期的分支工作流

如何做到这一点?

4

1 回答 1

1

这应该可以通过创建Task一个与两组 User 有关系的新工作流类型来实现Group(例如,a/b 或之前/之后,最好在模型定义中保持这个通用性)。

这个新Task的可以作为WorkflowWagtail 管理员中新的一部分创建,并且每个组都链接到版主组 1 / 2。

Wagtail 上的方法Task允许您根据Page模型为任何创建的工作流返回批准选项,从这里您可以查找将在类上的方法并从那里分配组。

使用更多通用方法的好处是,您可以将其用于任何主持人分配的拆分,作为未来工作流任务的一部分。

实施概述

  • 1 - 阅读有关如何添加新任务类型Task模型参考的 Wagatail 文档以了解此过程。
  • 2 - 通读内置代码中的完整实现GroupApprovalTask
  • 3 - 在GroupApprovalTask您可以看到,具有覆盖的方法都依赖于检查,self.groups但它们都将page作为 arg 传入这些方法。
  • 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_lockuser_can_unlockget_task_states_user_can_moderateget_approval_groupGroupApprovalTask

示例代码片段

模型.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, user, **kwargs):
        # Note: this has not been tested, however as this method does not get `page` we must find all the tasks allowed indirectly via their TaskState pages

        tasks = TaskState.objects.filter(status=TaskState.STATUS_IN_PROGRESS, task=self.task_ptr)

        filtered_tasks = []
        for task in tasks:
            page = task.select_related('page_revision', 'task', 'page_revision__page')
            groups = self.get_approval_groups(page)
            if groups.filter(id__in=user.groups.all()).exists() or user.is_superuser:
                filtered_tasks.append(task)

        return TaskState.objects.filter(pk__in=[task.pk for task in filtered_tasks])

    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)


于 2021-09-05T02:10:47.800 回答