Django 多數據庫配置與使用總結


Django 多數據庫配置與使用總結

 

By:授客 QQ:103355122

 

#實踐環境

Win 10

 

Python 3.5.4

 

Django-2.0.13.tar.gz

官方下載地址:

https://www.djangoproject.com/download/2.0.13/tarball/

 

#需求描述

項目開發中,部分業務功能的實現,需要跨數據庫查詢,並且想通過Django自帶ORM來實現

 

#解決方案

為Django配置多數據庫,具體操作步驟如下:

 

1、修改項目settings.py DATABASES配置

打開settings.py ,修改DATABASES配置—-為需要連接的數據庫新增配置(本例中以mysql數據庫配置為例,假設需要鏈接兩個數據庫)

 

# ...略

DATABASES = {
     # 默認數據庫配置
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'database_name', # 自定義數據庫名稱
        'USER': 'db_username',
        'PASSWORD': 'db_user_password',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'CONN_MAX_AGE': 30,
        'OPTION': {
            'init_command': 'SET default_storage_engine=INNODB'
        }
    },
    'secondDb': { #secondDb代表第二個數據庫的配置#該名稱可自定義
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'second_db_name', 
        'USER': 'db_username ',
        'PASSWORD': 'db_user_password',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'CONN_MAX_AGE': 30,
        'OPTION': {
            'init_command': 'SET default_storage_engine=INNODB'
        },
    },
#...略
}

  

為了方便描述下文內容,這里暫且把上述的 default,secondDb等稱為“數據庫配置結點”

 

2、修改項目settings.py DATABASE_ROUTERS路由配置

 

打開settings.py ,修改DATABASE_ROUTERS配置(如果不存在,則新增該配置項)

 

DATABASES = {

#...略

}

 

DATABASE_ROUTERS = ['Package.database_routers.DatabaseRouters']

 

說明:

Package: 路由規則文件所在包(一般是項目根目錄下,與項目同名的包目錄,或者app根目錄(包目錄))

 

database_routers: 定義路由規則的.py文件名稱,該文件名稱可以自定義

 

DatabaseRouters:上述.py中,定義路由規則的類名稱,該類名可自定義

 

DATABASE_ROUTERS為列表,所以,可以配置多個不同的路由

 

3、建立app應用和數據庫的映射關系

在settings.py中新增app和數據庫的映射關系(如果沒有的話),即針對指定app,配置其需要連接的數據庫

 

APP_DATABASE_MAPPING = { # 映射配置名稱,可自定義

'mysite': ' defualt', # 格式說明 'app名稱':'數據庫配置結點' # 注意,這里的“app名稱”,必須在settings.INSTALLED_APPS中已注冊,“數據庫配置結點”要同 settings.DATABASE 保持對應,兩者皆不能隨便自定義

'myblog': 'secondDb',

}

 

4、配置不允許執行migration操作的app(確切的說是app的model)

APPS_NOT_ALLOW_MIGRATE = ['myblog'] # 配置 app-label 為 myblog 的 model 不允許執行migration操作

 

 

5、創建數據庫路由規則

在項目根目錄下,與項目同名的目錄下(與 settings.py 文件位於同一目錄)創建路由規則.py文件(例中為 database_routers.py )

 

項目代碼工程結構目錄如下

TMP

|--TMP

    |--settings.py

    |--database_routers.py

|--manage.py

|--...略

|--mysite

|--myblog

 

database_routers.py內容如下:

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-


'''
@Author :shouke
'''

from django.conf import settings

DATABASE_MAPPING = settings.APP_DATABASE_MAPPING

DATABASES_NOT_ALLOW_MIGRATE = settings.APPS_NOT_ALLOW_MIGRATE


class DatabaseRouters(object):
    def db_for_read(self, model, **hints):
        """"指定mode進行讀取操作時應使用的數據庫, 如果返回None則表示使用默認數據庫"""

        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None


    def db_for_write(self, model, **hints):
        """指定mode進行寫入操作時應使用的數據庫, 如果返回None則表示使用默認數據庫"""

        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None


    def allow_relation(self, obj1, obj2, **hints):
        """控制是否允許obj1和obj2建立關聯關系,供外鍵和多對多操作使用,如果返回True則表示允許,如果返回False則阻止建立關聯關系,如果返回None則表示僅允許在相同數據庫內的對象建立關聯關系(備注:筆者親測,執行save()保存包含關聯外鍵對象,或者通過某個對象獲取關聯外鍵對象,該函數都不會被執行     
        """

        db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
        db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
        if db_obj1 and db_obj2:
            if db_obj1 == db_obj2:
                return True
            else:
                return False
         return None


    def allow_migrate(self, db, app_label, model=None, **hints):
        """指定是否允許在別名為db的數據庫上運行遷移操作。如果允許運行,則返回True;否則返回False、None"""

        if app_labelin DATABASES_NOT_ALLOW_MIGRATE:
            return False
        else:
            return True

  

 

6、創建mode表

在對應app中,創建對應數據表的models,不過,需要注意的是,需要根據上述路由規則,及實際需求,考慮是否為model指定app_label,如果不指定,在默認數據庫上執行相關操作。

 

以下為樣例數據表 mode

class BugType(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='自增id')
    bug_type = models.CharField(max_length=50, verbose_name='bug類型')

    class Meta:
        db_table = 'tb_bug_type'
        app_label = 'mysite'
        verbose_name = 'bug類型表'
        verbose_name_plural = verbose_name

class SprintBug(models.Model):
    id = models.AutoField(primary_key=True, verbose_name='自增id')
    name = models.CharField(max_length=10, verbose_name='bug名稱')
    but_type_id = models.IntegerField()

    class Meta:
        db_table = 'tb_sprint_bug'
        app_label = 'myblog'
        verbose_name = '迭代bug表'
        verbose_name_plural = verbose_name

  

 

 

說明:

這里假設SprintBug Model對應數據表為項目中需要跨數據庫查詢的且已存在的數據表,所以,希望在當前項目中執行migrate操作操作時,不對它進行創建、或者修改其數據表,僅供ORM操作使用,為了達到這個目的,需要顯示指定 db_table 為該據表在數據庫中的表名,並且顯示指定app_label值,並確保該 app_label 值存在上述settings.APPS_NOT_ALLOW_MIGRATE列表中(根據上述路由規則,app_label值存在settings.APPS_NOT_ALLOW_MIGRATE列表中的mode不允許執行migration操作)。

 

7、執行數據庫遷移操作

如果還沒執行遷移操作,需要先執行遷移操作,以便創建、修改model對應的數據庫表

python manage.py makemigrationsappName

python manage.pymigrate

 

 

說明:

如果希望執行migrate操作時,對應app對應model的migrations操作,在指定數據庫中執行,則需要使用 --database 選項,否則,沒指定app_label的model對應數據表相關操作將在默認數據庫中執行。

 

例子:把mysite的數據庫遷移操作放到 myAppDb1 代表的數據庫中執行。

python manage.py makemigrationsmysite

python manage.py--database=myAppDb1 # 注意,--database選項值實為settings.py中目標數據庫的“數據庫配置結點”,且該選項值不能加引號、雙引號,否則會報錯

 

這樣以后,其它所有的創建、查詢、刪除等操作就和普通一樣操作就可以了,無需再使用類似

models.User.objects.using(dbname).all()這樣的方式來操作。

   

#參考鏈接

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

 

  

 


免責聲明!

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



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