【发布时间】:2017-12-14 13:20:21
【问题描述】:
TLTR: Django 不在 SQL 查询中包含数据库名称,我可以强制它这样做还是有解决方法?
长版:
我有两个 legacy MySQL 数据库(注意:我对数据库布局没有影响),我正在为其创建一个只读 API 在 Django 1.11 和 python 3.6 上使用 DRF
我正在使用此处建议的 SpanningForeignKey 字段解决 MyISAM 数据库的引用完整性限制:https://stackoverflow.com/a/32078727/7933618
我正在尝试通过多对多通过 DB1 上的表将 DB1 中的表连接到 DB2 中的表。这就是 Django 正在创建的查询:
SELECT "table_b"."id" FROM "table_b" INNER JOIN "throughtable" ON ("table_b"."id" = "throughtable"."b_id") WHERE "throughtable"."b_id" = 12345
这当然会给我一个错误“表 'DB2.throughtable' 不存在”,因为 throughtable 在 DB1 上,我不知道如何强制 Django 在表前加上 DB 名称。查询应该是:
SELECT table_b.id FROM DB2.table_b INNER JOIN DB1.throughtable ON (table_b.id = throughtable.b_id) WHERE throughtable.b_id = 12345
app1 的模型db1_app/models.py: (DB1)
class TableA(models.Model):
id = models.AutoField(primary_key=True)
# some other fields
relations = models.ManyToManyField(TableB, through='Throughtable')
class Throughtable(models.Model):
id = models.AutoField(primary_key=True)
a_id = models.ForeignKey(TableA, to_field='id')
b_id = SpanningForeignKey(TableB, db_constraint=False, to_field='id')
app2 的模型db2_app/models.py: (DB2)
class TableB(models.Model):
id = models.AutoField(primary_key=True)
# some other fields
数据库路由器:
def db_for_read(self, model, **hints):
if model._meta.app_label == 'db1_app':
return 'DB1'
if model._meta.app_label == 'db2_app':
return 'DB2'
return None
我可以强制 Django 在查询中包含数据库名称吗?或者有什么解决方法吗?
【问题讨论】:
-
您是否尝试从
mysql客户端运行这样的查询?成功了吗? -
是的,
SELECT table_b.id FROM DB2.table_b INNER JOIN DB1.throughtable ON (table_b.id = throughtable.b_id) WHERE throughtable.b_id = 12345有效。正如我所说,问题在于 Django 没有将数据库名称添加到查询中的表中。 -
Django 的跨数据库关系是个难题。许多关于 Django 错误跟踪器的拉取请求或提案已被拒绝,原因很明确,主要是因为不完整。 (缺少其他后端、迁移、测试、对未来问题的恐惧、核心开发的可持续性和复杂性以进行微小改进)我发现一些 SO 问题过于复杂,无法期待任何进展。由于期望仅与遗留数据库的关系,这个问题非常现实。这是一个很好的起点。我奖励 Art 以表彰他对 PostgreSQL 的贡献。这里还没有完美的答案。
标签: python mysql django django-database