使用多个数据库的 Django 错误关系“auth_user”不存在

Posted

技术标签:

【中文标题】使用多个数据库的 Django 错误关系“auth_user”不存在【英文标题】:Django error relation "auth_user" does not exist using multiple database 【发布时间】:2017-02-19 04:11:12 【问题描述】:

我正在使用多个数据库(同一个 postgresql 数据库中的不同架构)处理 Django 1.9 和 python 3.3 项目。当我第一次尝试迁移项目时,我收到了这个错误

运行迁移: 渲染模型状态...完成 正在应用 contenttypes.0001_initial... 好的 正在应用 auth.0001_initial... OK 应用 MyApp.0001_initial...Traceback(最近一次调用最后一次): 文件“/usr/lib/python3.4/site-packages/django/db/backends/utils.py”,第 64 行,在执行 返回 self.cursor.execute(sql, params) psycopg2.ProgrammingError:错误:关系“auth_user”不存在 上述异常是以下异常的直接原因: 回溯(最近一次通话最后): 文件“manage.py”,第 10 行,在 execute_from_command_line(sys.argv) 文件“/usr/lib/python3.4/site-packages/django/core/management/__init__.py”,第 350 行,在 execute_from_command_line 实用程序.execute() 文件“/usr/lib/python3.4/site-packages/django/core/management/__init__.py”,第 342 行,在执行 self.fetch_command(子命令).run_from_argv(self.argv) 文件“/usr/lib/python3.4/site-packages/django/core/management/base.py”,第 348 行,在 run_from_argv self.execute(*args, **cmd_options) 文件“/usr/lib/python3.4/site-packages/django/core/management/base.py”,第 399 行,在执行中 输出 = self.handle(*args, **options) 文件“/usr/lib/python3.4/site-packages/django/core/management/commands/migrate.py”,第 200 行,在句柄中 executor.migrate(目标,计划,fake=fake,fake_initial=fake_initial) 文件“/usr/lib/python3.4/site-packages/django/db/migrations/executor.py”,第 92 行,在 migrate self._migrate_all_forwards(计划,full_plan,fake=fake,fake_initial=fake_initial) _migrate_all_forwards 中的文件“/usr/lib/python3.4/site-packages/django/db/migrations/executor.py”,第 121 行 state = self.apply_migration(状态,迁移,fake=fake,fake_initial=fake_initial) 文件“/usr/lib/python3.4/site-packages/django/db/migrations/executor.py”,第 198 行,在 apply_migration state = migration.apply(state, schema_editor) 文件“/usr/lib/python3.4/site-packages/django/db/backends/base/schema.py”,第 90 行,在 __exit__ 自我执行(sql) 文件“/usr/lib/python3.4/site-packages/django/db/backends/base/schema.py”,第 110 行,在执行 cursor.execute(sql,参数) 文件“/usr/lib/python3.4/site-packages/django/db/backends/utils.py”,第 79 行,在执行中 return super(CursorDebugWrapper, self).execute(sql, params) 文件“/usr/lib/python3.4/site-packages/django/db/backends/utils.py”,第 64 行,在执行 返回 self.cursor.execute(sql, params) 文件“/usr/lib/python3.4/site-packages/django/db/utils.py”,第 95 行,在 __exit__ 六.reraise(dj_exc_type,dj_exc_value,回溯) 文件“/usr/lib/python3.4/site-packages/django/utils/six.py”,第 685 行,在 reraise 提高 value.with_traceback(tb) 文件“/usr/lib/python3.4/site-packages/django/db/backends/utils.py”,第 64 行,在执行 返回 self.cursor.execute(sql, params) django.db.utils.ProgrammingError:错误:关系“auth_user”不存在

auth_user 表未迁移时,其他项目中似乎出现此错误。在我的情况下,在迁移需要它的应用程序之前使用 manage.py migrate auth 开始迁移并不能解决问题。

我怀疑问题来自在 Django 中使用不同的数据库。我的auth_user 表存储在默认数据库中,models.py 的内容被路由到其他数据库

迁移过程是否在与我的应用数据库相同的数据库中查找 auth_user 表?是不是完全不一样?

【问题讨论】:

【参考方案1】:

问题解答

其实是跨数据库引用的问题。 Django 无法创建跨数据库外键。

来自Django 1.8 documentation(并且下一个版本没有任何解决方案(当前版本是1.10)):

跨数据库关系

Django 目前不支持外键或 跨越多个数据库的多对多关系。如果你有 使用路由器将模型分区到不同的数据库,任何外来的 这些模型定义的键和多对多关系必须是 单个数据库的内部。

这是因为参照完整性。为了维持一个 两个对象之间的关系,Django 需要知道 相关对象的主键有效。如果主键是 存储在单独的数据库中,无法轻松评估 主键的有效性。

如果您将 Postgres、Oracle 或 mysql 与 InnoDB 一起使用,这是 在数据库完整性级别强制执行 – 数据库级别密钥 约束防止创建无法验证的关系。

但是,如果您将 SQLite 或 MySQL 与 MyISAM 表一起使用,则有 没有强制的参照完整性;因此,您可以 “假”跨数据库外键。不过这个配置不 由 Django 官方支持

如何解决和保留单独的数据库

在我的例子中,因为路由器正在工作,所以有一个小技巧可以简化跨数据库对象。

class CrossDBUser(models.Model):
    user = models.IntegerField()

    def get_user(self):
        return User.objects.get(id=self.user)

    def set_user(self, user):
        self.user = user.id

class MyClassWithCrossDB(CrossDBUser):
    field1 = models.CharField(max_length=200, blank=False)
    field2 = models.IntegerField(default=0)

有了这个,我可以使用方法set_userget_user 来处理存储在我的对象MyClassWithCrossDB 中的用户。

当然它并不完美,因为它不允许像on_delete=models.CASCADE 这样的自动化操作,而且我不得不使用方法而不是实例变量。但它是一种解决方法。

【讨论】:

以上是关于使用多个数据库的 Django 错误关系“auth_user”不存在的主要内容,如果未能解决你的问题,请参考以下文章

如何在 1:m 关系中设置默认值,Django 中 user_auth_model 的外键

Django auth详解

Django:无法创建与一个普通模型具有一对一关系的多个模型对象

Django权限系统:auth

Django权限系统auth模块详解

Django 13 admin和auth系统权限问题