Django:有没有办法为过去的迁移状态检索ORM?

时间:2015-11-02 20:24:27

标签: python django orm django-south

假设你有一个Django模型:

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

然后将其迁移到:

from django.db import models

class Person(models.Model):
    both_names = models.CharField(max_length=30)

你可能会为这种情况写一个数据迁移(或者我的,不是上面的,但是类似的,并且不能解决问题),你肯定想要测试它。

我使用call_command('migrate', app, state)将数据库回滚到旧状态,然后我想我只是使用Person的历史ORM来实例化一些Person个对象,然后执行迁移,然后做一些断言来检查我的数据迁移是否正常。

South中,您只需按Migration调出旧的ORM即可。如何在Django 1.8中执行此操作?

我的策略基于此文档:https://micknelson.wordpress.com/2013/03/01/testing-django-migrations/ 我希望找到Django historic-models的实现:https://docs.djangoproject.com/en/1.8/topics/migrations/#historical-models

重述问题 - 如何获得Person的'旧'状态,以便创建一个这样的人:Person(first_name='bob', last_name='jones') - 用于测试目的。

2 个答案:

答案 0 :(得分:2)

公共API不提供任何方法来获取迁移之外的历史模型。但是,您可以使用以下代码获取它:

from django.db import connection
from django.db.migrations.loader import MigrationLoader

loader = MigrationLoader(connection)
state = loader.project_state(loader.applied_migrations)
apps = state.apps

appsRunPython操作中传递给函数的对象相同。您可以使用apps.get_model('<app_label>', '<ModelName>')获取当前应用的迁移的历史模型。

这应该适用于1.8和1.9。它可能会或可能不会在未来的版本中工作,但我发现为什么这部分API应该很快改变的原因很少。

答案 1 :(得分:1)

对于 Django 3.0 和 3.1 ,解决方案与@knbk 的答案大致相同,除了 project_state() 的输入参数只是一个像 ('<APP_LABEL>', '<MIGRATION_NAME>') 这样的元组而不是整个 applied_migrations字典。

您可以通过直接指定 <APP_LABEL><MIGRATION_NAME> 来获取指定应用程序从初始迁移到特定提交迁移的状态:

from django.db import connection
from django.db.migrations.loader import MigrationLoader

loader = MigrationLoader(connection)
state = loader.project_state(('your_app_label', '0023_alter_some_fields'))
apps = state.apps

注意上面的代码在运行迁移命令时不能使用(例如makemigrationssqlmigratemigrate),否则会导致递归调用栈错误。