Django 也提供一个可让你经过代码彻底控制数据库使用的 API 。手动定义数据库分配 优先于路由。数据库
你能够在 查询集 “链”中的任何点为 查询集 选择数据库。咱们经过在 查询集 上调用 using() 来获得使用指定数据库的另外一个 查询集 。spa
using() 使用一个参数:你想要运行查询的数据库的别名。例如:对象
>>> # 这会运行在“缺省”数据库上。 >>> Author.objects.all() >>> # 这一样会运行在“缺省”数据库上。 >>> Author.objects.using('default').all() >>> # 这会运行在“ other ”数据库上。 >>> Author.objects.using('other').all()
在使用 Model.save() 时加上 using 关键字能够指定保存到哪一个数据库。路由
例如,要把一个对象保存到 legacy_users 数据库应该这样作:字符串
>>> my_object.save(using='legacy_users')
若是你不定义 using ,那么 save() 方法会根据路由分配把数据保存到缺省 数据库中。get
当你已经在一个数据库中保存了一个对象后,你可能会使用 save(using=...) 把这个 对象移动到另外一个数据库中。可是,若是你没有使用恰当的方法,那么可能会出现意想不 到的后果。class
假设有以下的例子:object
>>> p = Person(name='Fred') >>> p.save(using='first') # (第一句) >>> p.save(using='second') # (第二名)
在第一名中,一个新的 Person 对象被保存到 first 数据库中。这时, p 尚未一个主键,所以 Django 执行了一个INSERT SQL 语句。这样就会建立一个 主键,并将这个主键分配给 p 。model
在第二句中,由于 p 已经有了一个主键,因此 Django 在保存对象时会尝试在新的 数据库中使用这个主键。若是 second数据库中没有使用这个主键,那就不会有问题, 该对象会复制到新数据库。方法
然而,若是 p 的主键在 second 数据库中已经使用过了,那么 second 使用 这个主键的已存在的对象将会被 p 覆盖。
有两种方法能够避免上述状况的发生。第一,你能够清除实例的主键。若是一个对象没有 主主键,那么 Django 会把它看做一个新对象,在保存到 second 数据库中时就不会 带来数据的损失:
>>> p = Person(name='Fred') >>> p.save(using='first') >>> p.pk = None # 清除主键。 >>> p.save(using='second') # 写入一个全新的对象。
第二种方法是在 save() 方法中使用 force_insert 选项来保证 Django 执行 一个 INSERT SQL:
>>> p = Person(name='Fred') >>> p.save(using='first') >>> p.save(using='second', force_insert=True)
这样能够保证名为 Fred 的人员在两个数据库中使用相同的主键。若是在保存到 second 数据库时主键已被占用,会抛出一个错误。
缺省状况下,一个现存对象从哪一个数据库获得,删除这个对象也会在这个数据库中进行:
>>> u = User.objects.using('legacy_users').get(username='fred') >>> u.delete() # 会从 `legacy_users` 数据库中删除
经过向 Model.delete() 方法传递 using 关键字参数能够定义在哪一个数据库中删除 数据。 using 的用法与 save() 方法中使用这个参数相似。
例如,假设咱们要把一个用户从 legacy_users 数据库移动到 new_users 数据库 可使用以下命令:
>>> user_obj.save(using='new_users') >>> user_obj.delete(using='legacy_users')
在管理器上使用 db_manager() ,可让管理器访问一个非缺省数据库。
例如,假设你有一个操做数据库的自定义管理器 User.objects.create_user() 。 由于 create_user() 是一个管理器方法,不是一个 查询集 ,因此你不能用 User.objects.using('new_users').create_user() 。( create_user() 方法 只能用于 User.objects 管理器,而不能用于,管理器衍生出的 查询集 。) 解决方法是使用 db_manager() ,就象下面这样:
User.objects.db_manager('new_users').create_user(...)
db_manager() 返回的是绑定到你指定的数据库的管理器的一个副本。
若是你在管理器中重载了 get_query_set() ,请确保在其父类中也调用了相同的方法 (使用 super() )或者正确处理管理器中的 _db 属性(一个包含要使用的数据库 名称的字符串)。
例如,若是你要从 get_query_set 方法返回一个自定义 查询集 类,那么你能够 这样作:
class MyManager(models.Manager): def get_query_set(self): qs = CustomQuerySet(self.model) if self._db is not None: qs = qs.using(self._db) return qs