Django 1.7数据迁移和用户组

Nic*_*iou 8 python migration django

我正在尝试使用django 1.7本机迁移系统实现数据迁移.这就是我所做的.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations


def create_basic_user_group(apps, schema_editor):
    """Forward data migration that create the basic_user group

    """
    Group = apps.get_model('auth', 'Group')
    Permission = apps.get_model('auth', 'Permission')
    group = Group(name='basic_user')
    group.save()

    perm_codenames = (
        'add_stuff',
        '...',
    )

    # we prefere looping over all these in order to be sure to fetch them all
    perms = [Permission.objects.get(codename=codename)
             for codename in perm_codenames]

    group.permissions.add(*perms)
    group.save()


def remove_basic_user_group(apps, schema_editor):
    """Backward data migration that remove the basic_user group

    """
    group = Group.objects.get(name='basic_user')
    group.delete()


class Migration(migrations.Migration):
    """This migrations automatically create the basic_user group.

    """

    dependencies = [
    ]

    operations = [
        migrations.RunPython(create_basic_user_group, remove_basic_user_group),
    ]
Run Code Online (Sandbox Code Playgroud)

但是当我尝试运行迁移时,我遇到了一个LookupError异常,告诉我没有找到带有'auth'标签的应用程序.

如何以干净的方式创建我的组,也可以在单元测试中使用?

Lou*_*uis 6

我已经完成了你想要做的事情.问题是:

  1. 1.71.8的文档非常清楚:如果要从其他应用程序访问模型,则必须将此应用程序列为依赖项:

    在编写RunPython使用非迁移所在应用程序模型的函数时,迁移的依赖项属性应包括所涉及的每个应用程序的最新迁移,否则您可能会收到类似于以下内容的错误:LookupError: No installed app with label 'myappname'当您尝试检索时RunPython函数中的模型使用apps.get_model().

    所以你应该依赖于最新的迁移auth.

  2. 正如您在评论中提到的那样,您将遇到一个问题,即您尚未创建要使用的权限.问题是权限是由附加到post_migrate信号的信号处理程序创建的.因此,在迁移完成之前,与迁移中创建的任何模型关联的权限都不可用.

    您可以通过以下方式执行此操作来解决此问题create_basic_user_group:

    from django.contrib.contenttypes.management import update_contenttypes
    from django.apps import apps as configured_apps
    from django.contrib.auth.management import create_permissions
    
    for app in configured_apps.get_app_configs():
        update_contenttypes(app, interactive=True, verbosity=0)
    
    for app in configured_apps.get_app_configs():
        create_permissions(app, verbosity=0)
    
    Run Code Online (Sandbox Code Playgroud)

    这也将为每个模型创建内容类型(也在迁移创建),请参阅下文,了解您应该关注的原因.

    也许你可能比我在上面的代码中更有选择性:更新一些关键应用程序而不是更新所有应用程序.我没有尝试过有选择性.而且,两个循环都可以合并为一个.我没有尝试过一个循环.

  3. Permission通过搜索获得对象,codenamecodename不保证是唯一的.两个应用可以调用模型Stuff,因此您可以拥有add_stuff与两个不同应用相关联的权限.如果发生这种情况,您的代码将失败.你应该做的是搜索codenamecontent_type,保证是唯一的.唯一content_type与项目中的每个模型相关联:两个具有相同名称但在不同应用程序中的模型将获得两种不同的内容类型.

    这意味着添加对contenttypes应用程序的依赖关系,并使用ContentType模型:ContentType = apps.get_model("contenttypes", "ContentType").


小智 1

因此,我弄清楚如何解决这个问题,并得到以下退出: get_model will only fetch Your model apps。我不确定这是否是一个好的做法,但它对我有用。

我只是直接调用模型并进行更改。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.contrib.auth.models import Group


def create_groups(apps, schema_editor):
    g = Group(name='My New Group')
    g.save()


class Migration(migrations.Migration):

    operations = [
        migrations.RunPython(create_groups)
    ]
Run Code Online (Sandbox Code Playgroud)

然后,只需应用 /manage.py migrate 即可完成。我希望它有帮助。