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)

 

 

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

參考:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM