Django Wagtail基于用户和用户角色的动态菜单

d7v8vwbk  于 2023-02-10  发布在  Go
关注(0)|答案(1)|浏览(197)

使用Django-Wagtail和Wagtail菜单。我想建立一个具有以下特征的系统。
1.我有一个用户类别(供应商、供货商)
1.每个创建的用户都需要是这两个类中的一个。
1.每类用户都有不同的角色,且角色因类而异,例如:供应商:财务、库存、行政供应商:财务,股票,行政,司机
我所做的是创建一个名为UserType的类,"Vendor"和"Supplier"都是从这个类继承的,然后在User类中添加一个字段,用于选择用户类型。

class UserType(model.Model):
    common fields.......

class Vendor(UserType):
    child_vendor_only_fields.....

class Supplier(UserType):
    child_supplier_only_fields.....

class User(AbstractUser):
    userVar = models.ForeignKey(UserType, on_delete=models.SET_NULL, null=True, blank=True)

我还使用了wagtail admin为每个类创建自定义角色,如上所述。
显然,"供应商"可以创建、读取、更新和删除的内容与"供应商"不同。在此范围内,财务角色在"供应商"中可以做的事情与"库存"可以做的事情不同。
如何创建一个动态菜单,显示这些排列的不同菜单?
我最初的想法是受到this的启发。

USER_TYPE_CHOICES = (
('Vendor', 'Vendor'),
('Supplier', 'Suplier'))

class GenericPage(MenuPage):
    """
    This model will gain the fields, methods and `setting_panels` attribute
    from `MenuPage`, but `settings_panels` is being overridden to include
    other fields in the `Settings` tab.
    """
    availableTo = CharField(choices=USER_TYPE_CHOICES,)

    # 'menupage_panel' is a collapsible `MultiFieldPanel` with the important
    # fields already grouped together, making it easy to include in custom
    # panel definitions, like so:
    settings_panels = [
        FieldPanel('custom_settings_field_one'),
        menupage_panel
    ]

我有两个问题:
1.为用户类型生成自定义菜单的路径是否正确?如果正确,如何为用户类型下的角色执行相同操作?
1.就CRUD而言,我是否应该在每次用户执行一个crud操作时简单地检查他们是否可以实用地提交该操作?

eagi6jfj

eagi6jfj1#

对于CRUD,我不喜欢给别人做某件事的选择权,然后在事后告诉他们这个选项是不允许的。他们可能花了半个小时创建/编辑这个页面,然后发现他们浪费了时间。最好在页面加载时告诉他们。
对于用户类型,我只需要创建那些角色,然后添加用户到其中,然后对user.groups进行一个简单的测试,看看他们有什么角色。
你可以很容易地为你需要限制的每一个面板类型开发一个自定义的受限面板,如果它们都是FieldPanel,那就更容易了。在BoundPanel类中,你可以访问请求对象,所以你可以在运行时从请求对象中提取用户对象,然后决定接下来要做什么。
Panel.BoundPanel有一个方法is_showed(),所以你可以创建一个继承FieldPanel的自定义面板,重写该方法来测试请求用户是否在一个授权列表参数中,并相应地设置true/false。

# restricted_field_panel.py
from wagtail.admin.panels import FieldPanel

class RestrictedFieldPanel(FieldPanel):
    def __init__(self, field_name, authorised_groups, **kwargs):
        self.field_name = field_name
        self.authorised_groups = authorised_groups if isinstance(authorised_groups, list) else [authorised_groups]
        super().__init__(self.field_name, **kwargs)

    def clone_kwargs(self):
        kwargs = super().clone_kwargs()
        kwargs.update(
            authorised_groups=self.authorised_groups
        )
        return kwargs

    class BoundPanel(FieldPanel.BoundPanel):
        def is_shown(self):
            show_field = super().is_shown()
            is_authorised = self.request.user.groups.get_queryset().filter(name__in=self.panel.authorised_groups).exists()
            return (show_field and is_authorised)

在页面模型中:

content_panels = Page.content_panels + [
    RestrictedFieldPanel('some_vendor_field', 'Vendors'),
    RestrictedFieldPanel('some_supplier_field', 'Suppliers'),
    ....
]

对于授权组,您可能希望在默认情况下附加站点管理员角色,以便站点管理员始终可以看到任何受限面板。
其他面板类型需要继承并在渲染时进行测试。

相关问题