Django如何知道哪些迁移已经运行?

41

Django如何知道迁移是否已经应用?通常它能正确识别,但是当它无法识别时,我不知道从哪里开始排除故障。

5个回答

45

Django会将一条记录写入表格django_migrations,其中包括一些信息,如此次迁移所属的应用程序、迁移的名称以及应用时间。


@alecxe 在我的迁移历史表中存在一行 应用时间戳 - coldmind
@coldmind,我的错,你说得对。applied不是布尔标志——它是一个datetimefield。谢谢! - alecxe
1
在我的情况下,django_migrations 表中已经有一个条目,其中列出了我的应用程序和迁移(在这种情况下为 0001 initial)。然而,当我调用 ./manage.py migrate 时,Django 仍然尝试应用相同的迁移。./manage.py migrate <app> --fake-initialdjango_migrations 中创建了另一行,具有相同的 appname 字段(当然,appliedid 不同)。然后 ./manage.py migrate 最终报告没有要应用的迁移。这表明接受的答案是不完整的 - 为什么 Django 会尝试应用已列出的迁移? - Gabriel

27
您可以简单地使用 showmigrations 命令来提供迁移列表。
$ python manage.py showmigrations

每个迁移是否被应用(由迁移名称旁边的 [X] 标记表示)。

~/workspace $ python manage.py showmigrations
admin
 [X] 0001_initial
 [X] 0002_logentry_remove_auto_add
auth
 [X] 0001_initial
 [X] 0002_alter_permission_name_max_length
 [X] 0003_alter_user_email_max_length
 [X] 0004_alter_user_username_opts
 [X] 0005_alter_user_last_login_null
 [X] 0006_require_contenttypes_0002
 [X] 0007_alter_validators_add_error_messages
contenttypes
 [X] 0001_initial
 [X] 0002_remove_content_type_name
sessions
 [X] 0001_initial

2
Showmigrations会列出Django已知的迁移并告诉您它们是否已被应用。但是,它通过查看django_migrations表来生成此列表。每当运行迁移或成功回滚迁移时,该表都会得到更新。 - Kevin

9
如其他答案所述,Django有一个特殊的表django_migrations,它保存了迁移历史记录。
如果您对此感兴趣,可以查看MigrationRecorder,该类负责在数据库中记录迁移。此外,这里是django_migrations表的基本模型:
class Migration(models.Model):
    app = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    applied = models.DateTimeField(default=now)

    class Meta:
        apps = Apps()
        app_label = "migrations"
        db_table = "django_migrations"

    def __str__(self):
        return "Migration %s for %s" % (self.name, self.app)

9
使用 showmigrations 对于基本用例非常好。希望您永远不必使用超出此范围的内容。但是,如果您开始使用"替换"功能来压缩迁移,预期行为可能会变得极其复杂。
作为回答“Django 如何知道运行了哪些迁移?”问题的一部分,他们在数据库中存储已应用的迁移记录!
如果您想看看他们在数据库中存储了什么,请在 Django shell 中查看以下内容。
from django.db.migrations.recorder import MigrationRecorder
[(m.app, m.name) for m in MigrationRecorder.Migration.objects.all()]

对于简单的情况,这应该直接对应于使用 showmigrations 显示的内容。但是,如果合并了一些迁移(用其他迁移替换了一些迁移),您应该知道Django将数据库中存储的迁移与磁盘上存储的迁移进行比较,这个过程变得相当复杂。
因此,为了精确回答“Django如何知道已运行哪些迁移?”的问题,命令showmigrations显示Django迁移解析算法的结果,它使用了多个信息源,其中一个包括具有已应用的所有迁移的字面名称的表格。至于如何从一个转到另一个......请阅读源代码。

4
如果使用的是django1.7版本,它会将历史记录存储到数据库中的表django_migrations中。South也会将迁移信息存储在数据库中,并且您可以启用功能,在django管理界面中查看迁移历史记录。

看起来南方将迁移历史记录存储在 south_migrationhistory 表中,尽管我还没有找到官方文档来确认。 - CivFan
你知道如何启用在管理界面中显示迁移的功能吗?我在文档中找不到它,而且自己也无法成功实现。 - skolsuper
@skolsuper 或许有更好的解决方案,但你可以像这里描述迁移模型一样 https://github.com/django/django/blob/4373eac99828d99718a7b245d160e7e64fce2e95/django/db/migrations/recorder.py#L26,并将其像普通模型一样简单地包含到管理界面中。 - coldmind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接