1. 程式人生 > 其它 >Django 內設定讀寫分離

Django 內設定讀寫分離

1.啟動Mysql一主一從服務
Mysql的一主多從下,只有主庫才能進行讀寫,從庫只能讀不能寫
2.在setting.py,中首先配置多個數據庫

DATABASES = {
    #預設資料庫,配置多個mysql資料也是ok的,混用資料庫也是ok的
    'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'crm',
            'USER': 'root',
            'PASSWORD': 'xxxx',
            'HOST': '127.0.0.1',
            'PORT': '3306', #(主資料庫,所在埠)
        }

    #配置的第二個資料庫,注意資料庫名字不能相同
   'slave': {
              'ENGINE': 'django.db.backends.mysql',
              'NAME': 'crm',
              'USER': 'root',
              'PASSWORD': 'xxxx',
              'HOST': '127.0.0.1',
              'PORT': '3307', #(從資料庫,所在埠)
          }
}

3. 進行資料庫遷移

python manage.py makemigrations
python manage.py migrate 

在migrations資料夾下生成記錄,並在遷移前檢查是否有問題,預設值檢查defualt資料庫,但是可以在後面的資料庫路由類(Router)中通過allow_migrate()方法來指定是否檢查其它的資料庫。
其實第二步遷移預設有引數python manage.py migrate --database default ,在預設資料庫上建立表。
因為我採用的是Mysql的一主多從,遷移時候只需要遷移至主資料庫就行了,也就是預設的default資料庫,從資料庫會會自動根據主資料庫進行備份
4.怎麼實現讀寫分離


方法一:手動

def dbtest(request):
    # 向default資料庫中寫入資料
    # models.Class.objects.using('default').create(name='xx')

    # 從slave中讀取資料
    data = models.Class.objects.using('slave').all()
    # 更新時
    for i in data:
        i.name = 'xxxxxx'
        i.save(using='default') #更新時指定資料庫
    return render(request,'dbtest.html',{'data':data})

方法二:自動
a.在應用資料夾中建立一個py檔案(比如我寫在app01目錄下),名字隨意,比如叫做router.py檔案,寫上下面的內容

class Router:
    # 讀操作用default庫,就return這個庫名字串
    def db_for_read(self,model,**kwargs): # 方法名必須叫這個,不可更改
        return 'default'

    def db_for_write(self,model,**kwargs):# 方法名必須叫這個,不可更改
        return 'db2'

b.然後在 settings.py 配置檔案中做下面的配置

#寫上面這個類的路徑,我的是在app01應用資料夾下面的router.py檔案中了
DATABASE_ROUTERS = ['app01.router.Router',] 

c.那麼在邏輯的views.py檔案中寫的時候,就不需要using指定資料庫了

def dbtest(request):
    # 向default資料庫中寫入資料
    # models.Class.objects.create(name='xx')

    # 從slave中讀取資料
    data = models.Class.objects.all()
    # 更新時
    for i in data:
        i.name = 'xxxxxx'
        i.save() #更新時指定資料庫
    return render(request,'dbtest.html',{'data':data})

c.如果有多個應用,Mysql也有多個從從複製,也可以根據不同的應用來選擇不同的庫進行讀取

import random
class Router:
    # 讀操作用default庫,就return這個庫名字串
    def db_for_read(self,model,**kwargs):
        print(model)
        print(dir(model))# 其中有個_meta屬性很有用
        a = model._meta.app_label #獲取當前model物件所在的應用名稱     
        m = model._meta.model_name  獲取當前操作的model物件的表名,也可以根據表名來進行多資料庫讀的分配
        # 可以根據應用選擇不用的庫來進行讀取
        if a == 'app01':
            return 'slave01'
        elif a == 'app02':
            return 'db2'
        return 'slave02' # 假定mysql 設定了不止一個從檔案

    def db_for_write(self,model,**kwargs):

參考:
永遠的超哥 https://www.cnblogs.com/clschao/articles/11804924.html
不知名的好人 http://t.zoukankan.com/hanbowen-p-9899569.html