Django配置多数据库

1、定义数据库

在Django项目中,一个工程中存在多个app应用很常见,希望不同的app连接不同的数据库,这个时候需要建立多个数据库连接。

在Django的setting中使用DATABASE设置定义数据库,可以将数据库映射到特定的别名字典中

DATABASE定义的是给嵌套字典,该设置必须设置default默认数据库。默认使用SQLite进行单已数据库设置

 

1)DATABASE内部选项

ATOMIC_REQUESTS:为True的数据库事务包装每个视图,默认为False

AUTOCOMMIT:为False时禁用Django事务管理,默认为True

ENGINE:设置数据库类型

'django.db.backends.postgresql'
'django.db.backends.mysql'
'django.db.backends.sqlite3'
'django.db.backends.oracle'

 HOST:指定连接的主机名或ip地址,如果使用(‘/’)正斜杠开头则通过套接字连接:

'HOST':'127.0.0.1' #TCP套接字连接
'HOST':'/var/run/mysql' #UNIX套接字

NAME:指定使用的数据库名,对于SQLite它是指定数据库文件的路径,在window上也要使永正斜杠

'NAME':'databasename'
'NAME':'C:/user/mysite/sqlite3.db'

CONN_MAX_AGE:数据库连接的生命周期,默认为0请求结束时关闭数据库,设置为None无限持久连接

OPTIONS:链接到数据库时使用的额外参数,可用参数因数据库类型而异

'OPTIONS':{'read_default_file':'path/to/my.cnf',} #优先于NAME,USER,PASSWORD,HOST,PORT

#设置mysql启用严格模式
'OPTIONS':{'init_command':"SET sql_mode='STRICT_TRANS_TABLES'"}

PASSWORD:设置密码,不与SQLite一起使用

PORT:指定端口

TIME_ZONE:设置时区

DISABLE_SERVER_SIDE_CURSORS:True时禁用服务器游标

USER:连接用户名

TEST:测试数据库

 

2)自定义数据库

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'db1': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'HOST': '1.1.1.2',
        'USER': 'root',
        'PASSWORD': '123456',
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        }
    },
    'db2': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test',
        'HOST': '1.1.1.1',
        'USER': 'root',
        'PASSWORD': '123456',
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        }
    },
}

经测试:

这里启不启用OPTIONS(启不启用MySQL严格模式模式)都可以

 

2、同步数据库

migrate管理命令会同时在每一个数据库上运行,默认情况下它会在default数据库上运行,可以通过选项--database来指定需要同步的数据库。如不指定会同步到default数据库上。

 迁移同步命令:

makemigrations:根据检测到的变化创建新的迁移

migrate:将模型和迁移数据库同步到数据库中。

将每个应用同步到特定的数据库:

#python manage.py makemigrations   #检测变化生成migrate初始化脚本
#python manage.py migrate   #同步默认数据库
#python manage.py migrate --database=db1
#python manage.py migrate --database=db2

3、自动数据库路由

使用多个数据库时最简单的方法是设置数据库路由方案,以保证对象对原始数据库的“粘性”,默认所有的查询都会返回到default数据库中。

 

数据库路由是一个最多提供四种方法的类

db_for_read(model, **hints):应用于读取类型对象的数据库模型,如果数据库提供附件信息会在hints字典提供,最后如果没有则返回None

 

db_for_write(model, **hints):应用于写入模型对象的数据库模型,hints字典提供附件信息,如果没有则返回None

 

allow_relation(obj1, obj2, **hints):外键操作,判断两个对象之间是否是应该允许关系,是返回True,否则返回False,如果路由允许返回None

 

allow_migrate(db, app_label, model_name=None, **hints):db确定是否运行在具有别名的数据库上运行迁移操作,操作运行返回True,否则返回False,或者返回None,如果路由器没有意见。

 

app_label:位置参数是正在迁移的应用程序的标签

 

model_name:多个迁移操作设置模型的值,如:model.meta.app_label

 

1)定义数据库路由方法类

在项目根路径下(与setting.py文件一级)创建数据库路由表,app应该会根据指定的路由选择数据库

db_route.py

#!/bin/env python
# coding:utf8
from django.conf import settings

DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING  # 在setting中定义的路由表


class DatabaseAppsRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None

    def db_for_write(self, model, **hints):

        if model._meta.app_label in DATABASE_MAPPING:
            return DATABASE_MAPPING[model._meta.app_label]
        return None

    def allow_relation(self, obj1, obj2, **hints):

        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):

        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_name=None, **hints):
        if db in DATABASE_MAPPING.values():
            return DATABASE_MAPPING.get(app_label) == db
        elif app_label in DATABASE_MAPPING:
            return False
        return None

2)使用路由库

在setting.py文件中配置DATABASE_ROUTERS镇定自由路由文件:

# showNodeInstallNew为项目名,db_router为路由文件名,DatabaseAppsRouter为路由中创建的类名
DATABASE_ROUTERS = ['showNodeInstallNew.db_router.DatabaseAppsRouter']

在setting.py中DATABASE_ROUTERS下面设置app与数据库匹配路由表,采用字典方式app对应数据库映射名

DATABASE_APPS_MAPPING = { 'index': 'db1', 'nodeShow': 'db2', }

 

3)生成数据库表并同步数据

在index app里面创建models.py

from django.db import models

# Create your models here.
# 创建产品分类表
class Type(models.Model):
    id = models.AutoField(primary_key=True)
    type_name = models.CharField(max_length=20)

    class Meta:
        app_label = "index"

    def __str__(self):
        return self.type_name

# 创建产品信息表
class Product(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50)
    weight = models.CharField(max_length=20)
    size = models.CharField(max_length=20)
    type = models.ForeignKey(Type, on_delete=models.CASCADE)

    class Meta:
        app_label = "index"

在nodeShow app里面创建models.py

from django.db import models

# Create your models here.


# 创建m_auto_install_nodemanager_new表对象
class Nodemanager(models.Model):
    id = models.AutoField(primary_key=True)
    nodeName = models.CharField(max_length=64)
    stageName = models.CharField(max_length=64)
    installState = models.CharField(max_length=20)
    installInfo = models.CharField(max_length=1000)
    ts = models.DateTimeField(max_length=50)

    class Meta:
        app_label = 'nodeShow'

migrate管理命令一次只能操作一个数据库,默认操作default数据库,使用--database指定同步的数据库:

#python manage.py makemigrations #创建变动数据
#python manage.py migrate  #生成表数据同步
#python manage.py migrate --database=db1 #同步指定数据库
#python manage.py migrate --database=db2

 

需要注意:

在多个app分库时,必须指定每个app对应的数据库,否则在使用数据库时将没指定的app模板同步到同步数据库中。

 

4、不同应用使用不同数据库

在nodeShow app里面使用db1查询数据

配置urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('test.html', views.test),
    path('get_index.html', views.node_info)
]

配置views.py

def node_info(request):
    mysql_result = Nodemanager.objects.all().values()
    return render(request, 'nodeShow/node_info.html', locals())

配置html

{% load static %}
<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8">
   <title>查询数据</title>
   <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.css' %}">
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap-theme.min.css' %}">
    <link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap-theme.css' %}">
   <script src="{% static 'bootstrap/js/jquery.min.js' %}"></script>
   <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>

<div class="container table-responsive">
    <table class="table table-hover table-bordered table-condensed table-striped">
        <tbody>
            <tr class="success">
                <th class="text-center">id</th>
                <th class="text-center">nodeName</th>
                <th class="text-center">stageName</th>
                <th class="text-center">installState</th>
                <th class="text-center">installInfo</th>
                <th class="text-center">time</th>
            </tr>
            {% csrf_token %}
            {% for recode in mysql_result %}
            <tr class="active">
                <td>{{ recode.id }}</td>
                <td>{{ recode.nodeName }}</td>
                <td>{{ recode.stageName }}</td>
                <td>{{ recode.installState }}</td>
                <td>{{ recode.installInfo }}</td>
                <td width="170">{{ recode.ts }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>

</body>
</html>

猜你喜欢

转载自www.cnblogs.com/gentlemanhai/p/12000012.html