【问题标题】:Django : how to assign permissions automatically after initial migrationDjango:初始迁移后如何自动分配权限
【发布时间】:2021-07-17 19:07:27
【问题描述】:

我在后端使用Django,一切都很好。 但是我现在必须启用权限等等。 我试图在迁移过程中将应用程序的所有权限分配给一个组,但问题是:

在初始迁移期间,尚未创建权限。原因是在 Django 中,它们是在 post_migrate 信号中创建的。

见:

def ready(self):
   post_migrate.connect(
       create_permissions,
       dispatch_uid="django.contrib.auth.management.create_permissions"
   )
   # ...

django.contrib.auth.apps 中的ready() 方法中

默认流程是:

  • 调用migrate命令
  • 它做迁移的事情
  • 发送post_migrate 信号并创建权限记录

所以我也可以编写一个 post_migrate 函数,但是,我如何确定它会在创建权限的默认函数之后运行?

其他问题:有没有更好的方法在首次迁移应用时自动分配权限?

提前致谢:)

【问题讨论】:

    标签: django django-migrations django-permissions


    【解决方案1】:

    目前似乎不可能对 Permission 创建采取行动,因为它们是使用 bulk_create() 方法在 post_migrate 信号 (here) 中创建的。

    here

    1. 解决此问题的一种方法是改用create() 方法。我试图通过在 Django 票务系统(参见here)及其PR 上引入一张票来做到这一点。
    2. 第二种方法(只要维护bulk_create() 来创建权限,我就会使用该方法)是在ready() 方法(...) 中运行一个方法来分配它们。

    对于2) 解决方案,我最终得到了这个:

    def distribute_base_permissions():
        """ This method is used to automatically grant permissions of 'base' application
            to the 'Administrator' Group.
        """
        from django.contrib.auth.models import Group, Permission
        from django.contrib.contenttypes.models import ContentType
        group_content_type = ContentType.objects.get_for_model(Group)
        group, created = Group.objects.get_or_create(name="Administrator")
        for model in ContentType.objects.filter(app_label="base"):
            for perm in Permission.objects.filter(content_type__in=[model, group_content_type]):
                if (not group.has_permission(perm.codename) and
                    perm.codename not in model.model_class().UNUSED_PERMISSIONS):
                    group.add_permissions([perm])
    
    
    class BaseConfig(AppConfig):
        name = 'backend.base'
    
        def ready(self):
            distribute_base_permissions()
    

    该示例中有一些用于我的特定用例的精彩内容,我可以在运行时根据用户需要安装/卸载应用程序。

    我的base 应用程序默认安装,因此可以像这样分配其权限。

    对于我的可安装应用程序,除了不是在 ready() 方法中而是在我的自定义安装过程结束时完成之外,几乎相同:

    class Application(models.Model):
    
        class Meta:
            db_table = "base_application"
            verbose_name = "Application"
    
        # ...
        def migrate_post_install(self):
            # ...
            self.distribute_permissions()
    
        def distribute_permissions(self):
            """ This method is used to automatically grant permissions of the installed
                application to the 'Administrator' Group.
            """
            group, created = Group.objects.get_or_create(name="Administrator")
            for model in ContentType.objects.filter(app_label=self.name):
                for perm in Permission.objects.filter(content_type=model):
                    if (not group.has_permission(perm.codename) and
                        perm.codename not in model.model_class().UNUSED_PERMISSIONS):
                        group.add_permissions([perm])
    

    编辑:

    解决方案1) 已被拒绝,因为可以看到here。 讨论的一个解决方案是添加一个post_migrate 处理程序,但由于权限创建已经在post_migrate 中完成,我不知道如何确保我的信号处理程序将在创建权限的处理程序之后运行。 ..

    否则,似乎正在进行更改权限创建过程的工作,如here所示。

    【讨论】:

    • 这对我不起作用。应用迁移时,我从Group.objects.get_or_create(...) 行得到django.db.utils.OperationalError: no such table: auth_group
    • @MichaelHerrmann 这很奇怪。这意味着 auth_group 表不存在。您是否进行了初始迁移?我猜如果你执行migrate 命令,它应该先执行它们,但谁知道..?!
    • 我在运行测试时得到了这个,我想它可以一次性完成所有迁移。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-25
    • 2015-05-31
    • 2015-06-27
    • 2017-09-05
    • 1970-01-01
    • 2015-09-06
    • 2011-11-19
    相关资源
    最近更新 更多