栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

刨析django----配置多个数据库

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

刨析django----配置多个数据库

文章目录
  • django配置多个db
  • 数据库路由
  • 手动选择一个db

django配置多个db

如下,配置两个数据库:

DATABASES = {
	# 默认的数据库,没有选择其他数据库时,就使用默认的,不使用时,可以配置一个空字典
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        "HOST": "xxxx",
        "PORT": "xxx",
        'USER': 'postgres_user',
        'PASSWORD': 's3krit',
        'NAME': 'app_data',
    },
    # users应用连接的数据库
    'users': {
        'ENGINE': 'django.db.backends.mysql',
        "HOST": "xxx",
        "PORT": 3306,
        'USER': 'mysql_user',
        'PASSWORD': 'priv4te',
        'NAME': 'users_data',
    }
}

迁移时,一次操作一个数据库:

# 仅操作默认的db
python manage.py migrate

# 操作users(别名)数据库
python manage.py migrate --database=users

默认的数据库,不使用时,可以配置一个空字典,但必须得定义,如下:

DATABASES = {
    'default': {},
    'users': {
        'ENGINE': 'django.db.backends.mysql',
        "HOST": "xx",
        "PORT": 3306,
        'USER': 'mysql_user',
        'PASSWORD': 'superS3cret',
        'NAME': 'user_data',
    },
    'customers': {
        'ENGINE': 'django.db.backends.mysql',
        "HOST": "xxx",
        "PORT": "3306",
        'USER': 'mysql_cust',
        'PASSWORD': 'veryPriv@ate',
        'NAME': 'customer_data',
    }
}

此时,必须定义模型类的数据库路由
 

数据库路由

在主应用下创建database_router.py,内部定义数据库路由类。
数据库路由是一个类,提供如下四个方法:
db_for_read(model, **hints),模型类对象的读取

db_for_write(model, **hints),模型类对象的写入

allow_relation(obj1, obj2, **hints),表关系

allow_migrate(db, app_label, model_name=None, **hints), 是否允许迁移

1. 安装数据库路由:

# settings.py
# 配置数据库 一主两从
DATABASES = {
    'default': {},
    'auth_db': {
        'NAME': 'auth_db_name',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'swordfish',
    },
    'primary': {
        'NAME': 'primary_name',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'spam',
    },
    'replica1': {
        'NAME': 'replica1_name',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'eggs',
    },
    'replica2': {
        'NAME': 'replica2_name',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'bacon',
    },
}

# 配置 数据库路由
DATABASE_ROUTERS = ["project_name.database_router.AuthRouter", "xxx"]

# 按照顺序逐一查找

2. 定义数据库路由

# database_router.py
class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """
    # 指定使用某db的应用
    route_app_labels = {'auth', 'contenttypes'}

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        # 判断模型类的元类中的app_label
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'auth_db' database.
        app_label, 表示使用的数据库别名
        """
        if app_label in self.route_app_labels:
            return db == 'auth_db'
        return None

# 其他的应用  操作主从数据库
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_set = {'primary', 'replica1', 'replica2'}
        if obj1._state.db in db_set and obj2._state.db in db_set:
            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

在配置文件中,加入如下:

DATABASE_ROUTERS = ['project_name.database_router.AuthRouter', 'project_name.database_router。PrimaryReplicaRouter']

还需为应用下的模型类,指定使用的数据库:

class User(models.Model):
	...
	class Meta:
		db_table = "user"
		managed = True # 托管模式
		app_label = "users" # 通过users应用,使用指定的的db

# 迁移
python manage.py makemigratins users
python manage.py migrate users --database=auth_db
手动选择一个db

CRUD可以通过using(“xxx”)指定数据库,
优先级高于数据库路由

>>> # run on the 'default' database.
>>> Author.objects.all()
>>> Author.objects.using('default').all()

>>> # run on the 'other' database.
>>> Author.objects.using('other').all()

# 保存到指定数据库
>>> my_object.save(using='users_db')


# 主键重复问题
>>> p = Person(name='Fred')
>>> p.save(using='firstDB') # 先保存到第一个db 
>>> p.save(using='secondDB') # 再保存到第二个db,此时p是带有主键的,在写入第二个数据库时,会覆盖相同主键的数据,从而造成数据的丢失。采用如下方式解决: 
>>> p.pk = None # Clear the primary key.
>>> p.save(using='second') # 没有主键会被当成新对象,插入
或者采用强制插入的方式:
>>> p.save(using='second', force_insert=True)

# 保存与删除
>>> user_obj.save(using='new_users')
>>> user_obj.delete(using='legacy_users')

# 使用users_db 创建用户对象
>>> User.objects.db_manager('users_db').create_user(...)

django官网配置多个db

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/926304.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号