• Django笔记三十七之多数据库操作(补充版)


    本文首发于公众号:Hunter后端

    原文链接:Django笔记三十七之多数据库操作(补充版)

    这一篇笔记介绍一下 Django 里使用多数据库操作。

    在第二十二篇笔记中只介绍了多数据库的定义、同步命令和使用方式,这一篇笔记作为补充详细介绍如何对 Django 系统的多个数据库进行针对的建表同步操作。

    以下是本篇笔记目录:

    1. DATABASES 定义
    2. application创建和设置
    3. migration 和 migrate 操作
    4. 几个注意的点

    1、DATABASES 定义

    这里还是复用之前的 Django 系统,这里我们额外建立两个数据库连接,之前的 default 还是不变:

    # hunter/settings.py
    
    DATABASES = {
        'default': {
            ...
        },
        'user': {
            'ENGINE': "django.db.backends.mysql",
            'NAME': "db_1",
            "USER": "root",
            "PASSWORD": "123456",
            "HOST": "192.168.1.10",
            "PORT": 3306,
        },
        'other': {
            'ENGINE': "django.db.backends.mysql",
            'NAME': "db_2",
            "USER": "root",
            "PASSWORD": "123456",
            "HOST": "192.168.1.11",
            "PORT": 3306,
        },
    }
    

    数据库里的连接名称分别是 user 和 other。

    注意,这里我们使用的是不同的数据库 DATABASE,分别是 db_1 和 db_2,他们可以在一个地址的 MySQL 里,也可以在不同地址。

    2、application创建和设置

    接下来我们以 application 为整体来指定 model 对数据库进行操作。

    上面这句话这里释义一下,就是说针对多个数据库,我们这里默认使用整个 application 下的 model 表与之对应,比如说 new_user 这个 app 下的 model 的 migration 操作都写入 DATABASE 下 user 对应的数据库。

    当然,这个操作过程我们还需要在 settings.py 中定义一个映射 DATABASE_APPS_MAPPING,这个我们后面再说。

    创建application

    首先,我们分别创建两个 application,一个 application 名为 new_user,另一个名为 other_info,使用下面的命令创建:

    python3 manage.py startapp new_user
    
    python3 manage.py startapp other_info
    

    然后在系统的根目录会出现这两个文件夹。

    然后在 settings.py 中注册这两个 app:

    # hunter/settings.py
    
    INSTALLED_APPS = [
        ...
        'new_user.apps.NewUserConfig',
        'other_info.apps.OtherInfoConfig',
        ...
    ]
    

    application与数据库的对应设置

    然后设置 application 与 DATABASE 的对应关系:

    DATABASE_APPS_MAPPING = {
        "new_user": "user",
        "other_info": "other",
    }
    

    在这里的这个映射关系的 key 是我们的 application 的名称,value 则是 settings.py 中 DATABASES 对应的数据库的 key。

    比如这里我们将 new_user 这个 app 指定到了 user 数据库。

    创建 model

    接下来我们分别在两个 application 下创建对应的 model:

    # new_user/models.py
    
    from django.db import models
    
    class NewUser(models.Model):
        pass
    
        class Meta:
            app_label = "new_user"
    
    # other_info/models.py
    
    from django.db import models
    
    class OtherInfo(models.Model):
        pass
    
        class Meta:
            app_label = "other_info"
    

    在这两个 model 里,我手动给其添加了 app_label 字段,值为各自所在 application 下的名,表示这个 model 是从属于 app_label 这个 application 下。

    其实对于每个 model,meta 信息下都会有这个字段,默认值为该 model 所处的 application 的名称,这里为了显示对比,我额外标记了出来。

    查看 app_label 的方式为:

    from new_user.models import NewUser
    NewUser._meta.app_label
    
    # new_user
    

    而在前面的 settings.py 里我们设置了 DATABASE_APPS_MAPPING 映射

    DATABASE_APPS_MAPPING = {
        "new_user": "user",
        "other_info": "other",
    }
    

    所以这里的 NewUser model 使用的就是 user 这个数据库。

    接下来我们可以进行 migration 操作来测试将表结构写入 user 数据库。

    3、migration 和 migrate 操作

    接下来我们创建 migration 文件:

    python3 manage.py makemigrations new_user
    
    python3 manage.py makemigrations other_info
    

    然后会在 new_user 和 other_info 下分别创建对应的 migration 文件。

    接下来进行 migrate 的时候需要指定 database 参数,也就是我们前面 settings.py 里的 DATABASES 的对应的 key:

    python3 manage.py migrate new_user --database=user
    
    python3 manage.py migrate other_info --database=other
    

    根据 settings.py 里 DATABASE_APPS_MAPPING 里的映射关系,--database 对应的参数就是相应的数据库。

    执行完上面的命令之后,在两个对应的数据库里就会创建 django_migrations 表和 model 对应的表。

    创建 django_migrations 表是因为每个 database 也需要记录各自的 migration 迁移记录。

    至此,我们就将 application 下的 model 和 database 对应了起来。

    4、几个注意的点

    数据的增删改查

    前面我们将 model 和 database 对应了起来之后,在操作对应的 model 的时候还是需要 using() 来指定操作的 database:

    from new_user.models import NewUser
    NewUser.objects.using("user").create(id=1)
    

    default数据库

    在这篇笔记里,我们另外设置了两个数据库用于对应新建的 application,且在 DATABASE_APPS_MAPPING 中设置了 application 到 database 的映射,那么没有设置映射关系的 application 下的 model 其实就还是默认属于 default 数据库的。

    比如我们之前创建的 blog 这个 application,就相当于是:

    DATABASE_APPS_MAPPING = {
        "blog": "default",
        "new_user": "user",
        "other_info": "other",
    }
    

    不过因为是默认设置,所以为了方便我们没有显式的设置出来。

    并且,对于多个 application 是可以对应同一个数据库链接的,比如我们默认的 default,没有设置的 application 都对应的是 default 的数据库链接。

    假设我们又创建了一个名为 article 的 app,也想要对应 other 数据库,可以这样操作:

    DATABASE_APPS_MAPPING = {
        "blog": "default",
        "new_user": "user",
        "other_info": "other",
        "article": "other",
    }
    

    某 app 下设置其他 app 的 model

    这个操作是否可以呢?

    可以,假设我们在 new_user 下创建一个 model,但是设置的是 other_info 的 app_label:

    # new_user/models.py
    
    class OtherInfoInNewUser(models.Model):
        pass
    
        class Meta:
            app_label = "other_info"
    

    然后我们对 new_user 这个 app 执行下面的操作是检测不到有新 migration 的

    python3 manage.py makemigrations new_user
    

    因为当我们 makemigrations 指定 app 名称的时候,系统会去检测这个 app 下是否有属于这个 app 的新的 model 变化,而我们设置 OtherInfoInNewUser 这个 model 却从属于 other_info,所以是检测不到变化的。

    只有当我们执行:

    python3 manage.py makemigrations other_info
    

    这个操作的时候,系统才会检测到 app_label='other_info' 的 model 的变化,然后创建新的 migration。

    上面这个操作虽然是可行的,但是为了统一管理,还是不推荐这么操作。

    如果想获取更多后端相关文章,可扫码关注阅读:
    image

  • 相关阅读:
    Visual Studio 2019 VS编译ffmpeg4.4为静态库或动态库
    【LeetCode动态规划#13】买卖股票含冷冻期(状态众多,比较繁琐)、含手续费
    算法提升(一)二分法
    【C语言深入理解指针(4)】
    Ncnn框架在c++的推理及其认识
    express演示前端解决跨域的方法jsonp、cors
    Excel 数据透视表小技巧之 01如何取消透视表最后几行或最后几列的汇总
    【AIGC】逆向拆解OpenAI官方提示词Prompt技巧:高效提升ChatGPT输出质量
    在 GeoServer 上发布 Shapefile 文件作为 WMS 数据
    Vue3基础——条件渲染、列表渲染、事件&事件修饰符、父子组件间的数据传递、生命周期钩子
  • 原文地址:https://www.cnblogs.com/hunterxiong/p/17379315.html