django 项目中使用多数据库 multiple databases

假如在一个django项目中使用到了不仅一个数据库, 其实这在大一点的工程中很常见,好比主从库mysql

 

那么会涉及到以下一些东西sql

 

1, 定义数据库

在settings中的DATABASE中定义会使用到的数据,好比除default外咱们还定义了一个 searchdjango

 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, 使用app

 

会产生数据库操做的几个地方ui

  • Model对象
  • QuerySet
  • manager

 

 

假若有Model对象 objspa

它的save()会执行  INSERT 或  UPDATEcode

它的 delete() 会执行  DELETEorm

 

咱们拿到一个obj,或者建立一个新的obj后,使用非default db时,  参数中传进usingsqlite

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)

 

 

-----------------------

参考:

https://docs.djangoproject.com/en/1.6/topics/db/multi-db/

相关文章
相关标签/搜索