在使用多个数据库时将记录插入表的 ManyToMany 字段

Posted

技术标签:

【中文标题】在使用多个数据库时将记录插入表的 ManyToMany 字段【英文标题】:Inserting a record into a table's ManyToMany field while using multiple databases 【发布时间】:2019-12-25 12:14:29 【问题描述】:

我的项目使用 Django 的内置多数据库支持,我试图通过从一个数据库中获取记录并将其插入另一个数据库来同步 2 个不同数据库中的数据。

我尝试使用RelatedManager的add方法以通常的方式执行此操作,但它不起作用并且没有在第二个数据库的中间表中插入记录,而是在默认数据库中这样做。

我是这样做的: 我有一个 Person 模型,它有一个 ManyToMany 字段到 Dbs 模型:

...
class Person(models.Model):
    ...
    tenant_dbs = models.ManyToManyField(to=Dbs, blank=True)

和 Dbs 模型,其中包含单个列,其中包含一个人可以访问的数据库的名称:

...
class Dbs(models.Model):
    person_id = models.CharField(primary_key=True,
                                 max_length=20
                                 )

所以我想从默认数据库中获取一些 Person、Dbs 和中间记录并将它们全部复制到另一个数据库(假设它的名称是“辅助”)。所以我做了以下事情:

from core.models import Person
from .models import Dbs

#  here I take the objects from default db as I did not mention any other
#  db manually and save them in the 'secondary' db. This works fine and 
#  the records are duplicated to the db 'secondary'

p = Person.objects.get(pk='111')
p.save(using='secondary')
d = Dbs.objects.get(pk='some_db')
d.save(using='secondary')

# and now I retrieve the newly inserted records from the 'secondary' db and 
#  create a relation (insert a record into intermediary table, in other words)
#  using *add* method:
p2 = Person.objects.using('secondary').get(pk='111')
d2 = Dbs.objects.using('secondary').get(pk='some_db')

# **here is the problem: record is again inserted into default db
#  although it was retrieved from the 'secondary db'!**
p2.tenant_dbs.add(d) 

我清楚地看到表person_tenantdbs中没有添加任何记录,该表是在“辅助”数据库中的数据库级别自动创建的中间表。

所以我想知道如果数据库不是默认的,如何处理并在该表中插入一条记录?

我已经按照here 的描述尝试过使用管理器,如下所示:

...
p2.tenant_dbs.db_manager('secondary').add(d) 

但还是不行。

根据django源码,这个方法在多db的情况下好像只取router提供的db,见here:

db = router.db_for_write(self.model, instance=self.instance)

那么,有没有办法插入它并手动分配数据库,或者这只能通过路由器来完成?

我想在这方面寻求帮助,非常感谢。

【问题讨论】:

【参考方案1】:

这不是因为添加多对多。您只是忘记使用“使用”方法。

你应该改变这些

p = Person.objects.get(pk='111')
d = Dbs.objects.get(pk='some_db')

p = Person.objects.using('secondary').get(pk='111')
d = Dbs.objects.using('secondary').get(pk='some_db')

【讨论】:

以上是关于在使用多个数据库时将记录插入表的 ManyToMany 字段的主要内容,如果未能解决你的问题,请参考以下文章

在访问中将数据插入多个表的最佳方法?

如何在mysql 5中记录特定表的插入/更新查询

异常时将记录插入表中

如何仅在创建时将值插入数据库?(SQLite Android Studio)

在表中插入记录时将所选值作为城市下拉列表的空值

在java中获取数据库表的最后插入记录ID? [复制]