Django 多數據庫支持

不少時候,須要去其餘數據庫查詢數據,都將會面臨多數據庫支持問題.python

1.在settings文件內添加多數據庫鏈接mysql

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'test': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'pro_control',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '10.0.11.11',
        'PORT': '3306',
    }
}
若是默認數據庫的概念在項目上下文中沒有意義,則須要始終當心地指定要使用的數據庫。Django須要一個default數據庫,若是不須要使用,能夠設置爲空字典.
舉個栗子
DATABASES = {
    'default': {},
    'users': {
        'NAME': 'user_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'superS3cret'
    },
    'customers': {
        'NAME': 'customer_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_cust',
        'PASSWORD': 'veryPriv@ate'
    }
}
用例

若是你試圖鏈接一個沒有在DATABASES內定義的數據庫django將產生django.db.utils.ConnectionDoesNotExist異常sql

將模型同步到數據庫
./manage.py migrate  # 操做將同步到default數據庫
./manage.py migrate --database=test  # 同步到test數據庫

若是不是想全部的模型都同步到一個數據庫上你能夠定義一個database router,新建db_router.py文件數據庫

class AuthRouter:
    def db_for_read(self, model, **hits):
        if model._meta.app_label == 'test01':
            return 'test'
        return None

    def db_for_write(self, model, **hits):
        if model._meta.app_label == 'test01':
            return 'test'
        return None

    def allow_relation(self, obj1, obj2, **hits):
        if obj1._meta.app_label == 'test01' or obj2._meta.app_label == 'test01':
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hits):
        if app_label == 'test01':
            return db == 'test'
        return None

在setting文件內添加DATABASE_ROUTERS參數django

DATABASE_ROUTERS = ['test01.db_router.AuthRouter', ]

爲測試model指定,在test01的models文件內寫入app

from django.db import models
import shortuuid

# Create your models here.


def createuuid():
    return shortuuid.uuid()


class CourseManage(models.Model):
    """課程管控表"""
    uuid = models.CharField(
        'ID',
        max_length=22,
        primary_key=True,
        default=createuuid,
        editable=False)
    add_time = models.DateTimeField('建立時間', auto_now_add=True)

    del_state_type = ((0, '已刪除'), (1, '默認'))
    modified_time = models.DateTimeField('修改時間', auto_now=True)
    del_state = models.IntegerField(
        '刪除狀態', choices=del_state_type, default=1, db_index=True)
    config_status = ((1, '進行中'), (2, '完結'), )
    remote_id = models.CharField(verbose_name='遠端產品id', max_length=30)
    status = models.PositiveSmallIntegerField(choices=config_status, default=1)

    class Meta:
        verbose_name = '課程'
        verbose_name_plural = verbose_name
        db_table = 'backend_coursemanage'

db_table指定此模型在遠端的數據庫內的表名稱.否則會報錯dom

按照上述操做,便能鏈接並查詢.ide

 

標籤:當項目須要執行python manage.py makemigrations時,會發現,test01項目的migrations文件夾會產生migrations文件.而且終端也會產生提示,測試

能夠嘗試刪除此migrations,來避免這個問題,allow_migrate的判斷只針對真正的migrate操做.ui

 

如何選擇數據庫? 

1.模型層
User.objects.using('legacy_users').get(username='fred')
user_obj.save(using='new_users')
user_obj.delete(using='legacy_users')

2.原生光標

from django.db import connections
with connections['my_db_alias'].cursor() as cursor:
    ...

 

關於replication
DATABASES = {
    'default': {},
    'auth_db': {
        'NAME': 'auth_db',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'swordfish',
    },
    'primary': {
        'NAME': 'primary',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'spam',
    },
    'replica1': {
        'NAME': 'replica1',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'eggs',
    },
    'replica2': {
        'NAME': 'replica2',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'bacon',
    },
}
import random

class PrimaryReplicaRouter:
    def db_for_read(self, model, **hints):
        """
        Reads go to a randomly-chosen replica.
        """
        return random.choice(['replica1', 'replica2'])  # 這裏是重點

    def db_for_write(self, model, **hints):
        """
        Writes always go to primary.
        """
        return 'primary'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        db_list = ('primary', 'replica1', 'replica2')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        All non-auth models end up in this pool.
        """
        return True
相關文章
相關標籤/搜索