假设你有一个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')
- 用于测试目的。
答案 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
apps
与RunPython
操作中传递给函数的对象相同。您可以使用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
注意上面的代码在运行迁移命令时不能使用(例如makemigrations
、sqlmigrate
、migrate
),否则会导致递归调用栈错误。