django - 多數(shù)據(jù)庫及分庫實(shí)現(xiàn)

在django項(xiàng)目中, 一個工程中存在多個APP應(yīng)用很常見. 有時候希望不同的APP連接不同的數(shù)據(jù)庫携悯,這個時候需要建立多個數(shù)據(jù)庫連接充尉。

  1. 修改項(xiàng)目的 settings 配置
    在 settings.py 中配置需要連接的多個數(shù)據(jù)庫連接串
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'sqlite3'),
    },
    'db01': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db_01'),
    },
    'db02': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db_02'),
    },
}

假設(shè)現(xiàn)在我們用到3個數(shù)據(jù)庫撒遣,一個default默認(rèn)庫,一個 db01 和 db02

  1. 設(shè)置數(shù)據(jù)庫的路由規(guī)則方法
    在 settings.py 中配置 DATABASE_ROUTERS
DATABASE_ROUTERS = ['Prject.database_router.DatabaseAppsRouter']

Project: 建立的django項(xiàng)目名稱(project_name)
database_router: 定義路由規(guī)則database_router.py 文件名稱, 這個文件名可以自己定義
DatabaseAppsRouter: 路由規(guī)則的類名稱峭判,這個類是在database_router.py 文件中定義

  1. 設(shè)置APP對應(yīng)的數(shù)據(jù)庫路由表
    每個APP要連接哪個數(shù)據(jù)庫,需要在做匹配設(shè)置粒褒,在 settings.py 文件中做如下配置:
DATABASE_APPS_MAPPING = {
    # example:
    # 'app_name':'database_name',
    'app02': 'db02',
    'app01': 'db01',
    'admin': 'db01',
    'auth':  'db01',
    'contenttypes': 'db01',
    'sessions': 'db01',
}

以上的app01, app02是項(xiàng)目中的 APP名诚镰,分別指定到 db01奕坟, db02 的數(shù)據(jù)庫祥款。
為了使django自己的表也創(chuàng)建到你自己定義的數(shù)據(jù)庫中,你可以指定 : admin, auth, contenttypes, sessions 到設(shè)定的數(shù)據(jù)庫中执赡,如果不指定則會自動創(chuàng)建到默認(rèn)(default)的數(shù)據(jù)庫中

  1. 創(chuàng)建數(shù)據(jù)庫路由規(guī)則
    在項(xiàng)目工程根路徑下(與 settings.py 文件一級)創(chuàng)建 database_router.py 文件:
from django.conf import settings

DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING


class DatabaseAppsRouter(object):
    """
    A router to control all database operations on models for different
    databases.

    In case an app is not set in settings.DATABASE_APPS_MAPPING, the router
    will fallback to the `default` database.

    Settings example:

    DATABASE_APPS_MAPPING = {'app1': 'db1', 'app2': 'db2'}
    """

    def db_for_read(self, model, **hints):
        """"Point all read operations to the specific database."""
        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None

    def db_for_write(self, model, **hints):
        """Point all write operations to the specific database."""
        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """Allow any relation between apps that use the same database."""
        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_syncdb(self, db, model):
        """Make sure that apps only appear in the related database."""

        if db in DATABASE_MAPPING.values():
            return DATABASE_MAPPING.get(model._meta.app_label) == db
        elif model._meta.app_label in DATABASE_MAPPING:
            return False
        return None

    def allow_migrate(self, db, app_label, model=None, **hints):
        """
        Make sure the auth app only appears in the 'auth_db'
        database.
        """
        if db in DATABASE_MAPPING.values():
            return DATABASE_MAPPING.get(app_label) == db
        elif app_label in DATABASE_MAPPING:
            return False
        return None
  1. Models創(chuàng)建樣例
    在各自的 APP 中創(chuàng)建數(shù)據(jù)表的models時镰踏,必須要指定表的 app_label 名字,如果不指定則會創(chuàng)建到 default 中配置的數(shù)據(jù)庫名下沙合,
    如下:

在app01下創(chuàng)建models

class Users(models.Model):
    name = models.CharField(max_length=50)
    passwd = models.CharField(max_length=100)

    def __str__(self):
        return "app01 %s " % self.name

    class Meta:
        app_label = "app01"

在app02下創(chuàng)建models

class Users(models.Model):
    username = models.CharField(max_length=100)
    password = models.CharField(max_length=50)
    age = models.IntegerField()

    def __str__(self):
        return "app02 %s" % self.username

    class Meta:
        app_label = "app02"

class Book(models.Model):
    user = models.ForeignKey("Users", on_delete=models.CASCADE)
    bookname = models.CharField(max_length=100)

    def __str__(self):
        return "%s: %s" % (self.user.username, self.bookname)

    class Meta:
        app_label = "app02"

在 app03創(chuàng)建models 未指定 app_label奠伪,創(chuàng)建到default下

class Users(models.Model):?  
    username = models.CharField(max_length=100)
  1. 生成數(shù)據(jù)表
    在使用django的 migrate 創(chuàng)建生成表的時候首懈,需要加上 –database 參數(shù)滤否,如果不加則將 未 指定 app_label 的 APP的models中的表創(chuàng)建到default指定的數(shù)據(jù)庫中,如:

將app01下models中的表創(chuàng)建到db01的數(shù)據(jù)庫”db_01”中

./ manage.py  migrate  --database=db01     

將app02下models中的表創(chuàng)建到db02的數(shù)據(jù)庫”db_02”中

./ manage.py  migrate  --database=db02

將app03下models中的表創(chuàng)建到default的數(shù)據(jù)庫”sqlite3”中

./ manage.py  migrate

以上創(chuàng)建完成后,其它所有的創(chuàng)建、查詢最仑、刪除等操作就和普通一樣操作就可以了,無需再使用類似
models.User.objects.using(dbname).all()
這樣的方式來操作

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末藐俺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子泥彤,更是在濱河造成了極大的恐慌欲芹,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吟吝,死亡現(xiàn)場離奇詭異菱父,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)剑逃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門浙宜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蛹磺,你說我怎么就攤上這事粟瞬。” “怎么了萤捆?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵亩钟,是天一觀的道長。 經(jīng)常有香客問我鳖轰,道長,這世上最難降的妖魔是什么扶镀? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任蕴侣,我火速辦了婚禮,結(jié)果婚禮上臭觉,老公的妹妹穿的比我還像新娘昆雀。我一直安慰自己辱志,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布狞膘。 她就那樣靜靜地躺著揩懒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挽封。 梳的紋絲不亂的頭發(fā)上已球,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機(jī)與錄音辅愿,去河邊找鬼智亮。 笑死,一個胖子當(dāng)著我的面吹牛点待,可吹牛的內(nèi)容都是我干的阔蛉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼癞埠,長吁一口氣:“原來是場噩夢啊……” “哼状原!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起苗踪,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤颠区,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后徒探,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓦呼,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年测暗,在試婚紗的時候發(fā)現(xiàn)自己被綠了央串。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡碗啄,死狀恐怖质和,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情稚字,我是刑警寧澤饲宿,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站胆描,受9級特大地震影響瘫想,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望崔涂。 院中可真熱鬧蠕啄,春花似錦俱诸、人聲如沸尚镰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽窄驹。三九已至朝卒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乐埠,已是汗流浹背抗斤。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饮戳,地道東北人豪治。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像扯罐,于是被迫代替她去往敵國和親负拟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容