django 项目中使用多数据库 multiple databases
假如在一个django项目中使用到了不只一个数据库, 其实这在大一点的工程中很常见,比如主从库
那么会涉及到如下一些东西
1, 定义
在settings中的DATABASE中定义会使用到的数据,比如除default外我们还定义了一个 search
1 DATABASE = { 2 'default':{ 3 'ENGINE': 'django.db.backends.sqlite3', 4 'NAME': 'path/to/database.sqllite3', 5 'USER':'', 6 'PASSWORD':'', 7 'HOST': '', 8 'PORT':'', 9 }, 10 'search':{ 11 'ENGINE': 'django.db.backends.mysql', 12 'NAME': 'search_db', 13 'USER':'db_user', 14 'PASSWORD':'p@55word', 15 'HOST': '192.168.12.186', 16 'PORT':'', 17 } 18 }
2, 使用
会产生数据库操作的几个地方
- Model对象
- QuerySet
- manager
假如有Model对象 obj
它的save()会执行 INSERT 或 UPDATE
它的 delete() 会执行 DELETE
我们拿到一个obj,或者创建一个新的obj后,使用非default db时, 参数中传进using
obj = Person(name='wy', uid=530) obj.save(using='search') obj.delete(using='search')
通过manager拿到的都是QuerySet, 它对应数据库中的一个集合, 对应的语句是 SELECT
QuerySet有using方法, 指定去SELECT的数据库, 而QuerySet有一组方法是返回QuerySet对象的,所以只要在这个调用链中使用 using 就行
Person.objects.all().using('search').filter(uid__gt=100)
而manager本身提供了一个方法using, 这么定义的
def using(self, *args, **kwargs): return self.get_queryset().using(*args, **kwargs)
所以上面那行代码等效于
Person.objects.using('search').filter(uid__gt=100)
有时候我们会在manager层面设置使用的数据库. 比如对自定义的manager.
自定义的manager常见的一个情况是重写get_queryset()方法, 比如一个lady_manager,它可以重写get_queryset()只返回所有lady,然后再在这个基础上filter...
其实manager返回的QuerySet的_db是manager自己的_db传过去的, 而manager有 db_manager()这个方法来设置自身的_db
def db_manager(self, using): obj = copy.copy(self) obj._db = using return obj
所以只要这么用就好, 假如Person有一个自定义manager ladies
Person.ladies.db_manager('search').all()
3, admin使用多数据库
admin是django自带的一个app,那它涉及的是,读一个Model的所有对象(读一张表SELECT), 增加,删除,那么重写admin.ModelAdmin的如下几个做这几件事方法就好了
class MultiDBModelAdmin(admin.ModelAdmin): # A handy constant for the name of the alternate database. using = 'other' def save_model(self, request, obj, form, change): # Tell Django to save objects to the 'other' database. obj.save(using=self.using) def delete_model(self, request, obj): # Tell Django to delete objects from the 'other' database obj.delete(using=self.using) def get_queryset(self, request): # Tell Django to look for objects on the 'other' database. return super(MultiDBModelAdmin, self).get_queryset(request).using(self.using) def formfield_for_foreignkey(self, db_field, request=None, **kwargs): # Tell Django to populate ForeignKey widgets using a query # on the 'other' database. return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request=request, using=self.using, **kwargs) def formfield_for_manytomany(self, db_field, request=None, **kwargs): # Tell Django to populate ManyToMany widgets using a query # on the 'other' database. return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request=request, using=self.using, **kwargs)
如上代码摘自django文档,关于 formfield_for_foreignkey 和 formfield_for_manytomany 还没细研究
把上面的类定义放到自己的代码中,然后自己的ModelAdmin从它派生就行了, using中指定要使用的数据库, 如
class PersonAdmin(MultiDBAdmin): pass admin.site.register(PersonAdmin, Person)
-----------------------
参考: