django - 为什么我不能在 Django 的同一个迁移中为组分配新的权限

标签 django django-models django-migrations django-permissions

我正在尝试按照此 tutorial 添加新的迁移
我在 Meta 中添加了新权限进入 permissions field 。然后我创建了迁移并尝试修改此迁移以更新组权限。但是得到了DoesNotExistRunPython手术。

from django.db import migrations


def assign_new_permission(apps, *args):
    Permission = apps.get_model('auth.Permission')
    Group = apps.get_model('auth.Group')
    # __fake__.DoesNotExist: Permission matching query does not exist.
    new_permission = Permission.objects.get(
        codename='my_new_permissoin_code')

    admins = Group.objects.get(name='Group name')
    admins.permissions.add(new_permission)


class Migration(migrations.Migration):
    dependencies = [
        ('my_app', '0066_some_migratoin'),
    ]

    operations = [
        migrations.AlterModelOptions(
            name='my_model',
            options={'permissions': (('my_new_permissoin_code',
                                      'Permission name'),)},
        ),
        migrations.RunPython(assign_new_permission)
    ]

最佳答案

我认为您的问题出现是因为权限实际上不是在单个迁​​移期间或之后创建的,而是由在 python manage.py migrate 之后发送的迁移后信号触发的。命令成功完成(请参阅对已接受答案的评论 here 。)

有几种方法可以解决它:

  • 将其拆分为两个单独的迁移(创建权限然后分配它们)并使用两个单独的 python manage.py migrate 运行它们。命令:
    python manage.py migrate my_app 0066_create_permissions
    python manage.py migrate my_app 0067_assign_permissions
    

    这允许在运行 0066 以创建权限后发出迁移后信号。
  • 在一次迁移中将其分为两个步骤,但您必须使用 Python 函数手动创建权限,然后在另一个中分配它们。您必须修改您的 operations考虑到这一点。这样做的一个好处是,如果需要,您还可以创建一个或多个 Python 函数来反转迁移,这对于 #3 或 #4 来说实际上是不可能的。
  • 在迁移过程中自己发出迁移后信号。对于需要来自 3rd 方应用程序(如 django-guardian,就像我的情况)的权限的情况,这是一个很好的解决方案,以便您可以在数据迁移中应用它们。
    from django.apps import apps as django_apps
    def guardian_post_migrate_signal(apps, schema_editor):
        guardian_config = django_apps.get_app_config('guardian')
        models.signals.post_migrate.send(
            sender=guardian_config,
            app_config=guardian_config,
            verbosity=2,
            interactive=False,
            using=schema_editor.connection.alias,
        )
    
  • 这类似于#3,但更容易一些。可能有一些微妙的方式使情况变得更好或更糟,但我不确定它们是什么。您可以创建一个调用 django.contrib.auth.management.create_permissions 的函数。 (归功于 this post )并直接在您的迁移中使用它:
    from django.contrib.auth.management import create_permissions
    
    def create_perms(apps, schema_editor):
        for app_config in apps.get_app_configs():
            app_config.models_module = True
            create_permissions(app_config, apps=apps, verbosity=0)
            app_config.models_module = None
    

    那么你的 operations看起来像:
        operations = [
            migrations.AlterModelOptions(
                name='my_model',
                options={'permissions': (('my_new_permission_code', 'Permission name'),)},
            ),
            migrations.RunPython(create_perms),
            migrations.RunPython(assign_perms)
        ]
    

  • 无论如何,我希望这会有所帮助。抱歉信息过多 - 我过去遇到过和你一样的问题,这让我倒退了几天。

    关于django - 为什么我不能在 Django 的同一个迁移中为组分配新的权限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50114505/

    相关文章:

    python - Fab 未找到主机 key

    python - TypeError : int() argument must be a string, 类似字节的对象或数字,而不是 'DCountry'

    python - 为什么我的 Django 迁移会加载我的 urls.py?

    python - 在生产系统中重置 Django 迁移

    django - --fake-initial与--fake在Django迁移中?

    python - .gitignore 在 Windows 上开发 Python 和 Django 应用程序时

    django - 模块未找到错误 : No module named 'project.appname' when running Django tests

    python - Django 计算一对多关系

    python - django-多对多字段上的文件上传

    python - Django 管理中的 MultiValueDictKeyError