python – Django ManyToMany通过多个数据库
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – Django ManyToMany通过多个数据库,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4068字,纯文字阅读大概需要6分钟。
内容图文
TLTR:Django在SQL查询中不包含数据库名称,我可以以某种方式强制它执行此操作还是有解决方法?
长版:
我有两个遗留的MySQL数据库(注意:我对数据库布局没有影响),我正在使用Django 1.11和python 3.6上的DRF创建一个只读API
我正在使用此处建议的SpanningForeignKey字段来解决MyISAM DB的参照完整性限制:https://stackoverflow.com/a/32078727/7933618
我正在尝试通过MultiToMany通过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’不存在”因为ontable在DB1上,我不知道如何强制Django用数据库名称为表添加前缀.查询应该是:
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和sqlite后端,Django 1.6(包括1.11)存在一个解决方案,选项为ForeignKey.db_constraint=False和显式Meta.db_table.如果数据库名称和表名称由”'(对于MySQL)或”'(对于其他数据库)引用,例如db_table =’“db2”.“table2”’).那么它不会被引用更多并且有问题的查询是由Django ORM编译的.更好的类似解决方案是db_table =’db2“.”table2′(不仅允许连接,而且它也更接近跨越数据库约束迁移的一个问题)
db2_name = settings.DATABASES['db2']['NAME']
class Table1(models.Model):
fk = models.ForeignKey('Table2', on_delete=models.DO_NOTHING, db_constraint=False)
class Table2(models.Model):
name = models.CharField(max_length=10)
....
class Meta:
db_table = '`%s`.`table2`' % db2_name # for MySQL
# db_table = '"db2"."table2"' # for all other backends
managed = False
查询集:
>>> qs = Table2.objects.all()
>>> str(qs.query)
'SELECT "DB2"."table2"."id" FROM DB2"."table2"'
>>> qs = Table1.objects.filter(fk__name='B')
>>> str(qs.query)
SELECT "app_table1"."id"
FROM "app_table1"
INNER JOIN "db2"."app_table2" ON ( "app_table1"."fk_id" = "db2"."app_table2"."id" )
WHERE "db2"."app_table2"."b" = 'B'
Django中的所有db后端都支持该查询解析,但其他必要步骤必须由后端单独讨论.我试图更广泛地回答因为我找到了similar important question.
选项’db_constraint’是迁移所必需的,因为Django无法创建参考完整性约束
ADD外键table1(fk_id)REFERENCES db2.table2(id),
但它是can be created manually for MySQL.
特定后端的问题是,是否可以在运行时将另一个数据库连接到缺省值,并且是否支持跨数据库外键.这些模型也是可写的.间接连接的数据库应该用作managed = False的遗留数据库(因为只有一个表django_migrations用于迁移跟踪仅在直接连接的数据库中创建.此表应该只描述同一数据库中的表.)外键的索引可以但是,如果数据库系统支持此类索引,则可以在托管端自动创建.
Sqlite3:它必须在运行时附加到另一个默认的sqlite3数据库(回答SQLite – How do you join tables from different databases),最好是信号connection_created:
from django.db.backends.signals import connection_created
def signal_handler(sender, connection, **kwargs):
if connection.alias == 'default' and connection.vendor == 'sqlite':
cur = connection.cursor()
cur.execute("attach '%s' as db2" % db2_name)
# cur.execute("PRAGMA foreign_keys = ON") # optional
connection_created.connect(signal_handler)
那么它当然不需要数据库路由器和普通的django … ForeignKey可以与db_constraint = False一起使用.一个优点是,如果表名在数据库之间是唯一的,则不需要“db_table”.
在MySQL foreign keys between different databases中很容易.所有命令(如SELECT,INSERT,DELETE)都支持任何数据库名称,而不会先附加它们.
这个问题是关于遗留数据库的.然而,我对迁移也有一些有趣的结果.
内容总结
以上是互联网集市为您收集整理的python – Django ManyToMany通过多个数据库全部内容,希望文章能够帮你解决python – Django ManyToMany通过多个数据库所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。