Django 內設定讀寫分離
阿新 • • 發佈:2022-04-10
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