flask学习之flask-migrate 迁移数据库 (以及错误:Target database is not up to date的解决)

本文介绍如何使用Flask-Migrate进行数据库迁移,包括环境搭建、单文件与多文件配置示例,以及解决常见错误的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.flask-migrate使用背景

在实际的开发中,经常会发生数据库修改的行为,一般我们修改数据库不会直接手动的去修改,而是去修改ORM对应的模型,然后再把模型映射到数据库中,这时候如果有一个工具专门做这种事情,就显得非常有用了,而flask-migrate就是做这个事情的。
flask-migrate是基于alembic进行的一个封装,并且继承到flask中,而所有的迁移操作其实都是alembic做的,他能跟踪模型的变化,并且将变化映射到数据库中。

2.flask-migrate单文件版代码

#! C:\Python\Python36
# -*- coding: utf-8 -*-
# @Time : 2023-01-21 21:55
# @Author : liuchengyong
# @File : test2.py
# @Software: PyCharm
# config
import os
import sys
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
# DB_URI设置
HOSTNAME = '127.0.0.1'
DATABASE = 'class3'
PORT = 3306
USERNAME = 'root'
PASSWORD = 'root'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
# app设置
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# migrate配置
db = SQLAlchemy(app)
migrate = Migrate(app,db)

class User(db.Model):
    __tablename__ = 'username'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50))
    email = db.Column(db.String(50))
    # password = db.Column(db.String(50))
    # age = db.Column(db.Integer)

def add_data():
    admin = User(name='admin',email='admin@163.com')
    guest = User(name='guest',email='guest@163.com')
    db.session.add(admin)
    db.session.add(guest)
    db.session.commit()


@app.route('/')
def index():
    return 'lcy122'


if __name__ == '__main__':
    db.create_all()
    add_data()
    app.run()

换言之数据库迁移就是添加和减少字段,将最新的数据库版本号更新了。
在这里新增一个中间程序,存储db的中间程序,在这里只定义db而不进行相关的初始化。
以下为拆分版本
exts.py

from flask_sqlalchemy import SQLAlchemy
#from flask_app import app

db = SQLAlchemy()

在这里注释掉了from flask_app import app
因为如果采用以下写法:

from flask_sqlalchemy import SQLAlchemy
from flask_app import app

# db = SQLAlchemy()
db = SQLAlchemy(app)

就意味着在进行db初始化与赋初值时,exts从flask引用了app,而在引用db是在flask中进行的,进行了循环引用,这样会出问题,所以不对
应该采用第一种写法
models.py

from exts import db
#  db   database

class User(db.Model):
    __tablename__ = 'project_user'

    id = db.Column(db.Integer,primary_key=True,autoincrement=True)
    name = db.Column(db.String(50))
    email = db.Column(db.String(50))
    password = db.Column(db.String(50))
    age = db.Column(db.Integer)

config.py

HOSTNAME = '127.0.0.1'

# 数据库
# 几栋
DATABASE = 'demo2'

# 端口
# 门牌号
PORT = 3306

# 用户名和密码
# 钥匙
USERNAME = 'root'
PASSWORD = 'root'

DB_URL = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)


SQLALCHEMY_DATABASE_URI = DB_URL
SQLALCHEMY_TRACK_MODIFICATIONS = False

flask_app.py

from flask import Flask
import config
from exts import db
from models import User


app = Flask(__name__)
app.config.from_object(config)

#  db.create_all()  # 这个是干啥的?
db.init_app(app)

@app.route('/')
def index():
    return '这是首页'


if __name__ == '__main__':
    app.run(debug=True)

manage.py

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from flask_app import app
from exts import db
# 需要映射那个模型,就把哪个模型导入进来
from models import User

manage = Manager(app)

Migrate(app, db)

manage.add_command('db', MigrateCommand)


if __name__ == '__main__':
    manage.run()

在这里,入口程序为flask_app
manage.py程序是通过脚本启动的,因为有参数的,如果直接启动manage.py的话会报错,因为这个是命令行方式的入口,有参数的
错误信息:

usage: manage.py [-?] {db,shell,runserver} ...

positional arguments:
  {db,shell,runserver}
    db                  Perform database migrations
    shell               Runs a Python shell inside Flask application context.
    runserver           Runs the Flask development server i.e. app.run()

optional arguments:
  -?, --help            show this help message and exit

3.数据迁移操作

在启动flask_app之后,从cmd窗口启动manage.py进行migrate的初始化,在初始化完成之后会生成migrations文件夹,里面的versions文件夹内存在文件名为版本号加下划线的py文件,生成数据库的文件版本号与该版本号为一样的。
初始化:

python manage.py db init
(home) D:\flaskProject\testProject\test2\project_demo>python manage.py db init
Creating directory D:\flaskProject\testProject\test2\project_demo\migrations ...  done
Creating directory D:\flaskProject\testProject\test2\project_demo\migrations\versions ...  done
Generating D:\flaskProject\testProject\test2\project_demo\migrations\alembic.ini ...  done
Generating D:\flaskProject\testProject\test2\project_demo\migrations\env.py ...  done
Generating D:\flaskProject\testProject\test2\project_demo\migrations\README ...  done
Generating D:\flaskProject\testProject\test2\project_demo\migrations\script.py.mako ...  done
Please edit configuration/connection/logging settings in 'D:\\flaskProject\\testProject\\test2\\project_demo\\migrations\\alembic.ini' before proceeding.

数据库迁移:

python manage.py db migrate
(home) D:\flaskProject\testProject\test2\project_demo>python manage.py db migrate
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'project_user'
Generating D:\flaskProject\testProject\test2\project_demo\migrations\versions\cae239fcdbe4_.py ...  done

upgrade:

python manage.py db upgrade
(home) D:\flaskProject\testProject\test2\project_demo>python manage.py db upgrade
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade 779828c07852 -> 1ec2bc808ca7, empty message

完成之后查看数据库:

在这里插入图片描述
其中的alembic_version记录了最新版本号
查看project_user表格查看到内容
如果需要更改数据表的内容,可以进行后两步操作:

python manage.py db migrate
python manage.py db upgrade

然后可以发现alembic_version中的版本号更新了,数据表的字段也完成了更新

  • 中间遇到的问题 错误:Target database is not up to date.
(home) D:\flaskProject\testProject\test2\project_demo>python manage.py db migrate
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
ERROR [root] Error: Target database is not up to date.

查看了博客:
https://blog.youkuaiyun.com/qq_43193386/article/details/99959841
按照其中的方式,
找出versions文件夹内的版本号,去掉文件名最后的下划线后,将该版本号粘贴到数据库中的version_num下,再次进行migrate就可以正常运行了

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值