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