为什么django_migrations表存在于所有数据库中

7
我正在使用Django框架构建一个网站,这个网站需要有不同的SQL方案。目前,我已经成功创建了所有方案和相关内容,但我不明白为什么在数据库迁移后每个模式中都会出现django_migrations表。
  • 预期数据库内容:

    AppDB表是该应用程序定义的所有模型

    默认DB表是所有Django表(admin、contenttypes、auth、sessions)

  • 数据库内容:

    AppDB表是该应用程序定义的所有模型+django_migrations

    DEFAULT表是所有Django表(admin、contenttypes、auth、sessions)+django_migrations

这些是两个数据库的路由器:

class DefaultRouter(object):
    APPS = ['auth', 'sessions', 'admin', 'contenttypes']
    DB = 'default'

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.APPS:
            return self.DB
        return None

    def db_for_write(self, model, **hints):

        if model._meta.app_label in self.APPS:
            return self.DB

        return None

    def allow_relation(self, obj1, obj2, **hints):

        if obj1._meta.app_label in self.APPS or obj2._meta.app_label in self.APPS:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):

        if app_label in self.APPS:
            return db == self.DB
        return None


class MyAppDBRouter(object):
    def db_for_read(self, model, **hints):
        return self.check_app_label(model)

    def db_for_write(self, model, **hints):
        return self.check_app_label(model)

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'myapp' or obj2._meta.app_label == 'myapp':
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label == 'myapp':
            return db == 'appdb'
        return None

    @staticmethod
    def check_app_label(model):
        if model._meta.app_label == 'myapp':
            return 'appdb'
        return None

谢谢。

您已经写了一些回复答案的评论,但目前的问题描述似乎没有清楚地解释您所要问的问题。您能否编辑描述以更好地解释您所提出的问题? - bignose
3个回答

1
"

django_migrations表记录了已在该数据库上应用的迁移。这是Django迁移系统理解数据库当前状态以及需要运行哪些迁移的机制。因此,它在所有数据库上都是必需的。

现在,如果您有一个实际上不需要迁移的表,比如一个只读数据库,那么这可能会引起问题。这就是this ticket的主题。

"

我认为你没有理解我的问题,我的问题是这样的, 我有两个数据库,一个应该包含Django信息,另一个应该仅包含我的应用程序数据。 当我迁移项目时,它会在两个数据库中创建相同数据的django_migrations表,我尝试了几乎所有方法来避免这种情况,但没有任何帮助。 - Nadir Albajari
@NadirAlbajari:这是不可能的。你提到的其他表只是可选应用程序,可以放在任何地方。迁移表不是可选的,它必须存在于每个数据库中,以便跟踪已应用于该数据库的迁移。 - Kevin Christopher Henry
谢谢@Kevin,我明白了,但是假设我有两个应用程序(app1,app2)和两个数据库(db1,db2),我想在db1中为app1拥有相关的迁移,并且在db2中也是如此。但是db1中的迁移表包含了这两个应用程序的迁移,db2也是一样。 这是发生的好原因吗?有没有办法将两个应用程序的迁移分开呢?再次感谢! - Nadir Albajari
@NadirAlbajari:Django将这些迁移标记为已应用,但当allow_migrate()返回False时,实际上并不执行任何操作。这就是文档中“静默”一词的含义:“请注意,对于此返回值为False的模型,迁移将仅静默地不执行任何操作。”我的观点是这是一个糟糕的设计,你可以在我链接的票据中看到讨论。但这实际上给你带来了什么问题? - Kevin Christopher Henry
@KevinChristopherHenry 我知道这已经过时了,但5年后我偶然发现了同样的问题,即使路由器设置阻止实际表迁移到不需要的数据库,django_migrations表仍包含所有数据库的所有迁移。例如,我使用了 manage.py migrate polls --database=tutorial_db 来防止这种情况发生,其中 polls 选项仅尝试在投票应用程序上运行迁移,因此 django 的默认应用程序迁移不会出现在 tutorial_dbdjango_migrations 表中。不知道这是否是一个好的解决方案。有什么想法吗? - Kevin

1
在Django 1.7版本之前,没有django_migrations表。此后,Django正确地包括了用于处理数据库架构相关更改的迁移,即db.models中字段定义、添加或删除字段的更改。
在早期版本中,开发人员使用django_south_migration应用程序来执行此操作,但由于几乎每个人都在使用它,所以Django从1.7版本开始包含了它。
现在回到你的问题,django_migrations表记录了应用于数据库的数据库架构更改的记录。这个表帮助Django在运行python manage.py makemigrations后应用新的迁移。
该表的app列记录了应用此迁移的应用程序名称。如果您去任何Django应用程序的迁移目录,您将看到形式为0001_auto.py等的迁移文件。例如,如果此迁移已应用于数据库,则在django_migrations表中会找到一个名为0001_auto且app=的条目。

我认为你没有理解我的问题,我的问题是这样的, 我有两个数据库,一个应该包含Django信息,另一个应该仅包含我的应用程序数据。 当我迁移项目时,它会在两个数据库中创建相同数据的django_migrations表,我尝试了几乎所有方法来避免这种情况,但没有任何帮助。 - Nadir Albajari

0

当我运行python 'manage.py migrate --database=whatever'时,我遇到了与您相同的问题。当我检查dbshell时,我只能看到一个名为django_migrations的表...尝试了几次调整没有效果,然后我修改了路由器文件中我的数据库名称,这样就解决了!

例如,如果您称呼您的数据库为primary_db...您应该在路由器中使用在设置文件中注册的名称。请参考以下示例...

DATABASES = {
    'default': {},
    'primary': {
        'NAME': 'primary_db.sqlite3',
        'ENGINE': 'django.db.backends.sqlite3',        
    },
    'secondary': {
        'NAME': 'secondary_db.sqlite3',
        'ENGINE': 'django.db.backends.sqlite3',
    }
}

在您的路由器文件中使用primary作为名称,而不是primary_db...这就是我犯的错误...希望这可以帮助到您。

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