在Django中,我可以在创建对象时指定数据库吗?

时间:2015-10-08 08:48:34

标签: python django orm django-orm django-database

看看这个Django ORM代码:

my_instance = MyModel()
my_instance.some_related_object = OtherModel.objects.using('other_db').get(id)

此时,在第二行,Django将抛出一个错误:

ValueError: Cannont assign "<OtherModel: ID>": instance is on database "default", value is on database "other_db"

对我而言,这没有多大意义。 Django如何判断哪个数据库my_instance,如果我还没有调用:

my_instance.save(using='some_database')

了吗?

我想,在构造对象期间,Django会自动将其分配给default数据库。我可以改变吗?通过将参数传递给构造函数,我可以在创建对象时指定数据库吗?根据文档,在创建对象时,我可以传递的唯一参数是其字段的值。那我怎么解决我的问题呢?

在Django 1.8中有一个名为 Model.from_db https://docs.djangoproject.com/en/1.8/ref/models/instances/)的新方法,但我使用的是早期版本的Django并且无法切换现在更新。查看实现,它所做的只是设置两个模型的属性:

instance._state.adding = False
instance._state.db = db

将代码更改为:

就足够了
my_instance = MyModel()
my_instance._state.adding = False
my_instance._state.db = 'other_db'
my_instance.some_related_object = OtherModel.objects.using('other_db').get(id)

或者为时已晚,因为这些标志在构造函数中使用,只能在构造函数中设置?

2 个答案:

答案 0 :(得分:1)

您可能希望查看自Django 1.2以来一直受支持的database routing。这将允许您为不同的模型设置多个数据库(或“路由器”)。

您可以使用objectdb_for_read方法创建自定义数据库路由器(继承自内置db_for_write类型的类),该方法返回数据库的名称(如在DATABASES设置中)应该用于传递给该方法的模型。返回None让Django弄明白。

它通常用于处理主从复制,因此您可以从可写数据库中获得一个单独的只读数据库,但同样的逻辑适用于指定某些模型存在于某些数据库中。

您可能还需要定义一个allow_syncdb方法,以便只有您希望在数据库B中显示的模型出现在那里,其他所有模型都会出现在数据库A中。

答案 1 :(得分:1)

Django知道每个对象来自哪个数据库,因为它在其内部属性中对此做了说明。 QuerySet本身也存储了此信息。

实际上,实际上不需要数据库路由即可实现您想要的功能。

考虑以下代码片段:

my_instance = MyModel()
my_instance.some_related_object_id = OtherModel.objects.using('other_db').get(id).id

请注意,我仅分配ID,而不分配对象本身。

您将在这里丢失实际的对象,但是可以存储参考数据。

AFAIK没有用于更改对象关联数据库的API。