django 数据迁移 (migrations)

表已存在_错误参考
迁移常见错误解决方案
django官网迁移教程

  1. 执行启动迁移
DJANGO_ENV='test' python manage.py makemigrations --settings=iCrawler.settings_test main # main 为应用名 DJANGO_ENV='test' 为设置环境变量
  1. 执行迁移提交到数据库
DJANGO_ENV='test' python manage.py migrate main   --database=operation # main 迁移应用名 operation 为setting文件数据库参数名
  1. 如果出现数据库是最新的架构。 但是项目里面的migrations目录文件不是最新的这种情况的话。
    这个时候 启动迁移并提交为出现以下错误:

在这里插入图片描述
错误信息:

django.db.utils.ProgrammingError: relation "main_activitydeltalist" already exists

解决方案:

DJANGO_ENV='test' python manage.py migrate main   --database=operation  --fake # fake 参数代表当前提交迁移为假迁移 main 为应用名
  1. 出现这种 表已存在的错误, 说明 项目app目录下的migrations不是最新的。migrations 是根据迁移文件来判断是否有更新的表或字段。如果没有找到已迁移的文件就被视为未迁移,所以才会出现表已存在的错误信息。
    这个时候 我们把此次迁移做一个假迁移,也就是生成了一个迁移文件但是不提交到数据库,只是为migrations标识为最新的,即可解决。
  2. 也可以查看数据库中的migrations表 ,这个表的迁移记录一定是最新的。

Django多人开发模型迁移冲突问题解决

前提时以migrations文件提交到git中方式解决的方案。

在多人协作开发项目的时候,
遇到了多位开发同事 同时 修改了 相同模型类的情况下该怎么处理模型类迁移的问题,
譬如:

A开发者: 在分支1项目代码中添加一个 “author” 的字段到 ABCModel 中, 这样就有了 migration 0003_blog_blog.py
B开发者: 在分支2项目代码中添加一个 “content” 字段到 ABCModel 中,这样就有了 0003_blog_content.py

合并代码后该怎么执行迁移文件呢?
两个文件都是以 0003 编号 ?

解决方案:

  1. migration合并
    尝试执行 python manage.py migrate
    执行文件冲突的情况下, Django将提示你执行python manage.py migrations -merge 进行合并
    执行合并后会在migration文件夹中生成 0004_merge.py
    执行 python manage.py migrate 执行合并后迁移

  2. 回滚迁移文件至稳定状态
    使用 python manage.py migrate [APPName] [migrationNumber] 指定APP指定迁移文件进行回滚到最近稳定迁移状态
    重新生成迁移文件进行迁移 python manage.py migrations
    执行 python manage.py migrate 执行迁移

  3. 统一迁移
    开发项目可以对 migration 文件夹进行忽略
    开发仅仅需要对代码进行合并, 统一生成迁移文件并执行迁移

Django 个人开发时,官方推荐提交migrations文件

如果出现迁移文件冲突和重名可以按照以上方法操作,migrations合并迁移文件执行。

migrations原理

1 数据迁移

1.1 生成迁移文件(增量式)
  • (首次执行)根据models生成相应的迁移文件。
  • (再次执行)根据models和已有迁移文件差别,生成新的迁移文件
1.1.1 生成迁移文件 python manage.py makemigrations

首次执行python manage.py makemigrations命令,在app的makemigrations文件夹下生成迁移文件:
在这里插入图片描述

  1. makemigrations的作用是Django会去检查创建或修改数据库,如果不合法会给出提示。
  2. 当第一次执行该操作,会在app下面创建migrations目录,并创建0001_inital.py文件,文件中记录了当前的建表、依赖等信息。
  3. 当下一次执行该操作,对比历史的迁移文件,如果有关于model.py改动,会在migrations下生成已修改内容为名,类似0002_alter_permission_name_max_length.py的文件,文件中记录了你修改字段等信息。如果没有改动则提示:No changes detected
1.1.2 python manage.py migrate

执行完makemigrations只是生成了对应的sql语句,还并没真正将改动迁移到数据库中。需要执行migrate才能将改动迁移到数据库,完成建表、修改字段等操作。

迁移成功后会记录到django_migrations数据表中。
migrate 会检索迁移,通过django_migrations数据表查找,未找到代表未迁移。

django1.8+ 迁移回退

可以通过迁移到以前的迁移来恢复。

例如,如果最后两次迁移是:

0010_previous_migration
0011_migration_to_revert
回退迁移后, 数据库迁移记录表也会自动删除。
只是本地 迁移文件还存留着。

DJANGO_ENV='test' python manage.py migrate  main 0010_previous_migration   --database=operation

使用Django 1.8+,则可以显示所有迁移的名称及迁移状态。

DJANGO_ENV='test' python manage.py showmigrations  main   --database=operation

要逆转应用程序的所有迁移,可以运行:

./manage.py migrate my_app zero

django连接多个数据库机制原理

戳这里
戳这里2

django 多数据库下动态访问数据库,定制化数据库路由

官网教程
通过在setting配置文件中配置数据库路由(DATABASE_ROUTERS),自定义一个路由文件
如下:

# -*- coding: utf-8 -*-
"""
数据库 路由配置
"""

default_app_label = [
    # 'admin', 'auth', 'contenttypes', 'sessions',
    'main'
]
default_app_label2 = [
    'admin', 'auth', 'contenttypes', 'sessions',
    'meetingv2', 'guoteng'
]


# return falsle 代表拒绝此app操作 None 代表没意见跳过、None与True意思一样
# default_app_label的 app下的模型访问operation数据库,default_app_label2 的app模型访问 bayerynt_auxiliary_service数据库。否则 访问laravel_read数据库
class PrimaryRouter(object):
    
    def db_for_read(self, model, **hints):
    
        if model._meta.app_label in default_app_label:
            return 'operation'
        elif model._meta.app_label in default_app_label2:
            return 'bayerynt_auxiliary_service'
        return 'laravel_read'

    def db_for_write(self, model, **hints):
        if model._meta.app_label in default_app_label2:
            return 'bayerynt_auxiliary_service'
        return False

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label in default_app_label2 and obj2._meta.app_label in default_app_label2:
            return True
        return obj1._meta.app_label == obj2._meta.app_label

    def allow_migrate(self, db, app_label, model=None, **hints):
        if app_label in default_app_label2:
            return db == 'bayerynt_auxiliary_service'
        return False

四个方法 分别代表数据库的 读取、写入、数据库关系映射、数据迁移。
在方法中可灵活定义自己操作数据读写分离的规则。
注意:如果你要做迁移操作时、要迁移指定app下的模型。

  1. DJANGO_ENV=‘test’ python manage.py makemigrations --settings=iCrawler.settings_test 先从本地生成迁移文件,
    注意此处并不会过滤掉那些你不想迁移掉的app模型 会默认把setting下的app的模型全部生成。
  2. DJANGO_ENV=‘test’ python manage.py migrate --settings=iCrawler.settings_test --database=bayerynt_auxiliary_service
    只有在提交迁移的时候才会过滤。此处博主试验了多次。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

NET安梓晨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值