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

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',
    }
}

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

# 仅操作默认的 default 数据库
python manage.py makemigrations [appname]
python manage.py migrate [appname]

# 操作users(别名)数据库
python manage.py makemigrations
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:
        	# 允许迁移到auth_db
            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):
        """
        model, 传入的模型类,每次写入时都会走这里
        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):
        """
         db,允许迁移的数据库,默认是‘default’
         app_label, 应用的名字
         model_name, 模型类的名字
         model, 模型类
        """

		# 允许迁移
        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() # 默认查询default 数据库
>>> 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(...)

# 判断用户权限
>> user = User.from_db("primary", "username", "jack")
>> user.has_perm("add_user") # 是否有增加用户的权限 _user是User模型类
>> user.has_perms(["add_user", "delete_user", "view_user", "change_user"]) # 增删改查权限

django官网配置多个db

数据库路由

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

laufing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值