django多数据库操作

1. 读写分离

  • 192.168.1.2 default 主数据库负责写入
  • 192.168.1.3 slave 从数据库负责读取

2. 生成数据库表

python manage.py makemigrations
分别迁移到主从数据库
python manage.py migrate --database=default 
python manage.py migrate --database=slave 


多个app分表:分app操作数据库  假设app01对应数据库default,app02对应数据库slave

python manage.py makemigrations
python manage.py migrate app01 --database=default 
python manage.py migrate app02 --database=slave

 

3. 开发时手动选择使用数据库

models.UserInfo.objects.using("default").create(title="admin")
models.UserInfo.objects.using("slave").all()

4. 多数据库,多app操作配置

settings.py中增加数据库配置

DATABASE_ROUTERS = ['KPIBackendSys.database_router.DatabaseAppsRouter']   # 读写文件路径

DATABASE_APPS_MAPPING = {
    'app01': 'default',
    'app02': 'slave',
}

DATABASES = {
    # 默认AI数据库
    'default': {
        'ENGINE': 'mssql',                        # 要连接的 数据库类型
        # 'ENGINE': 'sql_server.pyodbc',          # 要连接的 数据库类型
        'NAME': db1,                # 要连接的 数据库名
        'HOST': host,                      # 要连接的远程数据库的 ip地址
        'PORT': port,                           # 数据库连接端口,mysql默认3306
        'USER': user,                         # 数据库已有用户名
        'PASSWORD': pwd,                   # 数据库已有用户密码
        'OPTIONS': {
            'driver': 'ODBC Driver 17 for SQL Server',
            'MARS_Connection': True,
        },
    },
    'slave': {
        'ENGINE': 'mssql',
        # 'ENGINE': 'sql_server.pyodbc',          # 要连接的 数据库类型
        'NAME': db2,
        'HOST': host,                  # 要连接的远程数据库的 ip地址
        'PORT': port,                       # 数据库连接端口,mysql默认3306
        'USER': user,               # 数据库已有用户名
        'PASSWORD': pwd,                # 数据库已有用户密码
        'OPTIONS': {
            'driver': 'ODBC Driver 17 for SQL Server',
            # 'MARS_Connection': True,
        },
    },
}

在settings.py同级目录下增加database_router.py文件

database_router.py

class DatabaseAppsRouter(object):
    def db_for_read(self, model, **hints):
        # 判断模型类的元类中的app_label
        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None
        # 或直接判断并返回数据库
        if model._meta.app_label == 'app01':
            return default
        if model._meta.app_label == 'app02':
            return slave

    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
        # 或直接判断并返回数据库
        if model._meta.app_label == 'app01':
            return default
        if model._meta.app_label == 'app02':
            return slave

    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.
        app_label, 表示使用的数据库别名
        """
        if db in DATABASE_MAPPING.values():
            # 允许迁移到auth_db
            return DATABASE_MAPPING.get(app_label) == db
        elif app_label in DATABASE_MAPPING:
            return False
        # 不允许迁移
        return None

5. 同一个app下的模型存储在不同的数据库

使用database_router.py中的allow_migrate方法, 读写操作同样需要指定数据库

class DatabaseAppsRouter(object):
    def db_for_read(self, model, **hints):
        # 判断模型类的元类中的app_label
        # 或直接判断并返回数据库
        if model._meta.model_name in [model1, model2]:
            return default
        if model._meta.model_name in [model3, model3]:
            return slave

    def db_for_write(self, model, **hints):
        # 或直接判断并返回数据库
        if model._meta.model_name in [model1, model2]:
            return default
        if model._meta.model_name in [model3, model3]:
            return slave

    def allow_migrate(self, db, app_label, model=None, **hints):
        
        if db == 'default':
          if model_name in ['model1', 'model2']:
            return True
          return False
         
        if db == 'slave':
          if model_name in ['model3', 'model4']:
            return True
          return False
        

posted @ 2024-08-04 10:34  星空28  阅读(14)  评论(0编辑  收藏  举报