django使用多个数据库实现

Posted 侯哥的Python分享

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django使用多个数据库实现相关的知识,希望对你有一定的参考价值。

一、说明:

  在开发 Django 项目的时候,很多时候都是使用一个数据库,即 settings 中只有 default 数据库,但是有一些项目确实也需要使用多个数据库,这样的项目,在数据库配置和使用的时候,就比较麻烦一点。

二、Django使用多个数据库中settings中的DATABASES的设置

  2.1 默认只是用一个数据库时 DATABASES 的设置(以 SQLite 为例)

DATABASES = 
    \'default\': 
        \'ENGINE\': \'django.db.backends.sqlite3\',         
        \'NAME\': \'db.sqlite3\',
    

  2.2 Django 数据库支持的 ENGINE 类型

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

  2.3 设置了多个数据库后 settings 中的 DATABASES 的设置

DATABASES = 
    \'default\': 
        \'ENGINE\': \'django.db.backends.sqlite3\',
        \'NAME\': \'db.sqlite3\',
    ,
    \'db1\': 
        \'ENGINE\': \'django.db.backends.mysql\',
        \'NAME\': \'mysql_test_db1\',
        \'USER\': \'root\',
        \'PASSWORD\': \'Se7eN521\',
        \'HOST\': \'127.0.0.1\',
        \'PORT\': \'3306\'
    ,
    \'db2\': 
        \'ENGINE\': \'django.db.backends.mysql\',
        \'NAME\': \'mysql_test_db2\',
        \'USER\': \'root\',
        \'PASSWORD\': \'Se7eN521\',
        \'HOST\': \'127.0.0.1\',
        \'PORT\': \'3306\'
    

三、实现思路

  1. 多个应用对应多个数据库和一个应用对应多个数据库
    1. 情况一:项目有多个 应用app 且需要使用到多个数据库
    2. 情况二:项目只有一个应用app, 且但需要使用到多个数据库,
  2. 这两种情况的实现思路其实都是一样的,都是为每个数据库创建一个应用,即这个应用只对接一个数据库,如果这个应用不需要写任何业务逻辑的代码,也需要创建一个空的应用,主要是用来做数据库迁移的
  3. 核心思想就是:一个model类对应一个数据库,通过数据库路由和model定义时指定的all_label来实现。

四、案例实现

  第一步:创建需要的 应用app,并且在 INSTALLED_APPS 中引用

    其中db1_app这个应用主要是用来对接数据库db1的

    其中db2_app这个应用主要是用来对接数据库db2的

    其中test_app这个应用主要用来实现业务逻辑的

                 

 

  第二步:创建 应用app 和 数据库之间的映射关系

    在settings.py 文件夹中设置 DATABASE_APPS_MAPPING 的字典,里面主要是配置 应用app 和数据库的对应关系

DATABASE_APPS_MAPPING = 
    "db1_app": "db1",   # db1_app 对应 db1 数据库
    "db2_app": "db2"    # db2_app 对应 db2 数据库

  第三步:创建数据库路由

    在项目的主文件夹即 settings.py 的同目录下创建一个 database_router.py 文件,该文件的作用就是给不同应用app 配置不同的数据库。

# _*_ coding:utf-8 _*_
# @Time : 2023/4/20 5:37 下午

from django.conf import settings

DATABASE_MAPPING = settings.DATABASE_APPS_MAPPING
print(\'DATABASE_MAPPING = \'.format(DATABASE_MAPPING))

class DatabaseAppsRouter(object):

    # 设置 应用app 读取时数据库的设置
    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_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure that apps only appear in the related database.
        根据app_label的值只在相应的数据库中创建一个表,如果删除该def或
        不指定过滤条件,则一个Model会在每个数据库里都创建一个表。
        """
        if db in DATABASE_MAPPING.values():return DATABASE_MAPPING.get(app_label) == db
        elif app_label in DATABASE_MAPPING:
            return False
        return None

  第四步:在setting.py中配置 DATABASE_ROUTERS 指定自由路由文件:

#test_django为项目名,database_router为路由文件名,DatabaseAppsRouter为路由中创建的类名
DATABASE_ROUTERS = [\'django_db_demo.database_router.DatabaseAppsRouter\']

  第五步:创建model类

    说明:model 可以根据需要卸载任何一个应用app的model.py文件中,也可以分散写在多个应用的model.py中,这个根据自己的需要即可,但是如何推荐一定要在model类的Meta中指定app_label。不然会全部将表创建到default数据库中

from django.db import models

class SqliteModel(models.Model):
    """帐号和用户关联"""

    sqlite_name = models.CharField(max_length=20)
    class Meta:
        # 当前这个 SqliteModel 定义的数据库的表将会创建在test_app 对应的default 数据库中
        app_label = "test_app"      # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库
        db_table = "sqlite_test_table"   # 自定义的表名

class Db1Model(models.Model):
    """帐号和用户关联"""

    db1_name = models.CharField(max_length=20)
    class Meta:
        # 当前这个Db1Model 定义的数据库的表将会创建在 db1_app 对应的 db1 数据库中
        app_label = "db1_app"        # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库
        db_table = "db1_test_table"    # 自定义的表名

class Db2Model(models.Model):
    """帐号和用户关联"""

    db2_name = models.CharField(max_length=20)
    class Meta:
        # 当前这个Db2Model 定义的数据库的表将会创建在 db2_app 对应的 db1 数据库中
        app_label = "db2_app"       # 当有多个数据库链接的时候,要通过app_label 来区分这个model对应那个数据库
        db_table = "db2_test_table"   # 自定义的表名

  

  第六步:数据迁移

python3 manage.py makemigrations  
python3 manage.py migrate --database=default   # 当有多个数据库,需要迁移多次
python3 manage.py migrate --database=db1
python3 manage.py migrate --database=db2 

  第七步:查看迁移:

    model对应的表,分别迁移到不同的数据库成功,剩下的增删改查的就正常引入model对象即可,这样就实现了,不同的model对象,对应不用数据库的表。

    

 第五步:总结

  1. 创建多个数据库连接设置
  2. 创建多个数据与应用app的映射关系
  3. 创建数据库路由
  4. 创建model类的时候置指明app_label,即这个model是属于那个app,从而觉得迁移到那个数据库

使用 bootstrap 和 django 在同一页面内实现两个或多个选项卡面板

【中文标题】使用 bootstrap 和 django 在同一页面内实现两个或多个选项卡面板【英文标题】:implementing two or more tab panel within same page using boootstrap and django 【发布时间】:2014-09-28 14:03:31 【问题描述】:

在我的 django 项目中,我使用了一个 for 循环来迭代以下代码块。因此产生了两个或多个引导面板,每个面板都包含一个选项卡面板。

我的问题是,当在浏览器中看到页面时,只有第一个面板有效。即,当我们单击第二个或第三个面板的选项卡时,数据更改发生在第一个面板的选项卡中!。

%for obj in temp%
    <section id="main-content">
    <section class="wrapper">
    <div class="row">

      <section class="panel"id="obj.case_id">

          <header class="panel-heading">
                      <span class="label label-success">Case ID as per user submision :</span><span class="label label-inverse">obj.case_id</span>
                      <span class="tools pull-right">
                          <a href="javascript:;"class="icon-chevron-down"></a>
                          <!-- <a href="javascript:;" class="icon-remove"></a> -->
                      </span>
          </header>
            <div class="panel-body">

                  <section class="panel" >
                          <header class="panel-heading tab-bg-dark-navy-blue ">

                              <ul class="nav nav-tabs">
                                  <li class="active">
                                      <a data-toggle="tab" href="#home">Case_ID</a>
                                  </li>
                                  <li class="">
                                      <a data-toggle="tab" href="#about">Agency</a>
                                  </li>
                                  <li class="">
                                      <a data-toggle="tab" href="#profile">Officer</a>
                                  </li>
                                  <li class="">
                                      <a data-toggle="tab" href="#contact">Upload date</a>
                                  </li>
                              </ul>
                          </header>
                          <div class="panel-body">
                              <div class="tab-content">
                                  <div id="home" class="tab-pane active">
                                      obj.case_id
                                  </div>
                                  <div id="about" class="tab-pane active">obj.case_description</div>
                                  <div id="profile" class="tab-pane">obj.officer.username</div>
                                  <div id="contact" class="tab-pane">obj.date_created</div>
                              </div>
                          </div>
                  </section>
            </div>     
      </section>
    </div>
  </section>
  </section>
    %endfor%

有关此问题的任何帮助。

【问题讨论】:

【参考方案1】:

一种可能的解决方案是使用迭代对象为每个选项卡添加一个唯一的 id:

<a data-toggle="tab" href="#home-obj.case_id">Case_ID</a>

在标签中:

<div id="home-obj.case_id" class="tab-pane active">
  obj.case_id
</div>

当然,您需要在您拥有的所有选项卡上应用此解决方案。

【讨论】:

以上是关于django使用多个数据库实现的主要内容,如果未能解决你的问题,请参考以下文章

Django连接多个数据库并实现读写分离

Django连接多个数据库并实现读写分离

使用 bootstrap 和 django 在同一页面内实现两个或多个选项卡面板

如何使用 django orm 将数据插入到多个表中

django 对多个数据库支持

Django实现SSO