编辑:
这些其他答案更有意义:
原文:
在实际应用它们之前,通过一些基本的单元测试运行您的数据迁移功能(例如 OP 示例中的 combine_names),这对我来说也很有意义。
乍一看,这应该不会比普通的 Django 单元测试困难多少:迁移是 Python 模块,migrations/ 文件夹是一个包,因此可以从中导入东西。但是,它需要一些时间才能使其正常工作。
第一个困难是由于默认迁移文件名以数字开头的事实。例如,假设 OP(即 Django 的)数据迁移示例中的代码位于 0002_my_data_migration.py,那么很容易使用
from yourappname.migrations.0002_my_data_migration import combine_names
但这会引发SyntaxError,因为模块名称以数字开头(0)。
至少有两种方法可以做到这一点:
-
重命名迁移文件,使其不以数字开头。根据docs,这应该很好:“Django 只关心每个迁移都有不同的名称。”然后你可以像上面一样使用import。
-
如果您想坚持使用默认编号的迁移文件名,可以使用 Python 的import_module(请参阅docs 和this SO 问题)。
第二个的困难在于您的数据迁移函数被设计为传递给RunPython (docs),因此默认情况下它们需要两个输入参数:apps和schema_editor。要查看这些来自哪里,您可以查看source。
现在,我不确定这是否适用于所有情况(请任何人评论,如果你能澄清的话),但对于我们的情况,从 django.apps 导入 apps 并获得 schema_editor 就足够了来自活动数据库connection (django.db.connection)。
以下是一个精简示例,展示了如何为 OP 示例实现此功能,假设迁移文件名为 0002_my_data_migration.py:
from importlib import import_module
from django.test import TestCase
from django.apps import apps
from django.db import connection
from yourappname.models import Person
# Our filename starts with a number, so we use import_module
data_migration = import_module('yourappname.migrations.0002_my_data_migration')
class DataMigrationTests(TestCase):
def __init__(self, *args, **kwargs):
super(DataMigrationTests, self).__init__(*args, **kwargs)
# Some test values
self.first_name = 'John'
self.last_name = 'Doe'
def test_combine_names(self):
# Create a dummy Person
Person.objects.create(first_name=self.first_name,
last_name=self.last_name,
name=None)
# Run the data migration function
data_migration.combine_names(apps, connection.schema_editor())
# Test the result
person = Person.objects.get(id=1)
self.assertEqual('{} {}'.format(self.first_name, self.last_name), person.name)