Django 1.7 - makemigrations 为非托管模型创建迁移

Posted

技术标签:

【中文标题】Django 1.7 - makemigrations 为非托管模型创建迁移【英文标题】:Django 1.7 - makemigrations creating migration for unmanaged model 【发布时间】:2014-12-24 06:27:03 【问题描述】:

我正在我的应用程序中创建一些动态 Django 模型,除了迁移系统之外,一切似乎都按预期工作。

如果我创建一个动态 Django 模型并设置 managed = False,Django 的 makemigrations 命令仍会为该新模型生成迁移。迁移看起来像这样:

class Migration(migrations.Migration):

    dependencies = [
        ('atom', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='books',
            fields=[
            ],
            options=
                'db_table': 'books',
                'managed': False,
            ,
            bases=(models.Model,),
        ),
    ]

如果我不创建迁移,当我运行 python manage.py migrate 时,我会看到以下消息(用大而可怕的红色字母表示):

Your models have changes that are not yet reflected in a migration, and so won't be applied.
Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

有没有办法告诉 Django 1.7 中的迁移系统一起忽略非托管模型?或者模型的 Meta 类中的 migrations = False 设置?

更新:为了澄清,我正在使用一种方法来创建我的动态模型,类似于以下地方描述的那些:

http://dynamic-models.readthedocs.org/en/latest/topics/model.html#topics-model https://code.djangoproject.com/wiki/DynamicModels

此方法非常适合根据存储在我的配置模型 (https://code.djangoproject.com/wiki/DynamicModels#Adatabase-drivenapproach) 中的信息生成我的动态模型。我确实必须注册一个信号来清除 django 模型缓存以在配置实例更改时捕获模型的更改,但一切似乎都很好,除了为这些模型生成迁移这一事实。如果我删除其中一个配置并且模型从 Django 的缓存中删除,则需要再次更新迁移,删除它不应该关心的模型。

这些动态模型并未专门用于应用程序中。我在代码中没有提到书籍模型(来自上面的示例)。它们在运行时生成并用于从它们提供访问权限的旧表中读取信息。

【问题讨论】:

但是迁移真的会导致问题吗?也就是说,当您运行migrate 时,它会在数据库中错误地创建模型吗?如果没有,那真的没有问题。迁移系统不仅关心数据库级别的更改,它还尝试在内存中创建尽可能准确的模型图片。 没错。迁移不会导致问题。但是,在动态系统中,始终存在潜在的新模型。如果我可以向迁移系统表明它不需要担心这些特定模型,那就太好了。 您能否向我们提供有关如何生成动态模型的更多详细信息?主要是动态生成它们需要什么数据。 【参考方案1】:

您可能可以编写一个自定义数据库路由器,使用allow_migrate 方法为您的动态模型返回False。在这种情况下,migrate 命令将禁止它们。

只要您不将这些动态模型加载到任何 models.py 模块中,makemigrations 也不应该拾取它们。

【讨论】:

嗯,这给了我一些更接近的东西,但并不完全如此。当我运行 makemigrations 命令时,仍然可以看到动态模型,并且正在为它们创建迁移。但是,它不会为这些表/模型运行迁移。理想情况下,我也可以覆盖类似 allow_makemigrations 的方法。【参考方案2】:

我建议您将生成的migrations.CreateModel 操作替换为您自己的一个始终反映实际模型状态的操作。这样就不会检测到任何状态变化。

class CreateDynamicModel(CreateModel):
    def __init__(self):
        # ... dynamically generate the name, fields, options and bases
        super(CreateDynamicModel, self).super(
            name=name, fields=fields, options=optins, bases=bases
        )

【讨论】:

【参考方案3】:

简短的回答是 Django 不是为此而构建的。使您的模型“不受管理”only means Django will not create or delete the table for it -- nothing else。

也就是说,如果您在同一个应用中除了这些动态模型之外没有常规模型,您可以有条件地将应用添加到 INSTALLED_APPS in settings.py

if not ('makemigrations' in sys.argv or 'migrate' in sys.argv):
    INSTALLED_APPS += (
        'app_with_dynamic_models',
        'another_app_with_dynamic_models',
    )

这应该让 Django 在创建和运行迁移时忽略应用程序。但是,如果您想使用模型,您最终将不得不为模型创建和运行迁移,因为the ability to have apps which do not use migrations is meant to go away in Django 1.9。您的动态模型能否重构为使用contenttypes framework?

【讨论】:

在 Django 1.11.5 上对我来说失败了。 Django 仍然尝试在包含非托管表的遗留数据库中创建 django_migrations 表。

以上是关于Django 1.7 - makemigrations 为非托管模型创建迁移的主要内容,如果未能解决你的问题,请参考以下文章

在迁移中获取模型 ContentType - Django 1.7

Django 1.7 迁移

无法将 Django 从 1.7 迁移到 1.8

python 将Django QuerySet作为JSON响应返回的示例(Django 1.7)

Django 1.7 - 提供静态文件

Django 1.7 makemigrations 没有效果