2021-01-25

关于alembic迁移修改models.py模型结构,却总是创建新的表的问题

之前尝试给公司做个小型的数据分析平台,使用vue+fastapi+sqlalchemy做前后端,使用request+lxml+apscheduler做爬虫框架。在搭建数据库的时候,发现修改模型(表结构),使用alembic生成迁移文件,修改数据表,生成的迁移文件总是会对老表重复create(add),然后在alembic upgrade head 的时候,就告诉你,什么表单已经存在,创建表单失败,明明你只是想修改表结构,然后他生成的迁移文件就创建个新表

如果出现了这种情况,主要原因有两种,也有可能两种问题同时都犯了

一般使用sqlalchemy构建ROM流程基本上都是这样:

# database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

SQLALCHEMY_DATABASE_URL = (
    "mysql+mysqlconnector://用户名:密码@数据库地址:3306/数据库名"
)
engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_size=1000, max_overflow=0)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

然后创建模型比如

# models.py
from sqlalchemy import Column, Integer, String, TIMESTAMP, Boolean, Float, TEXT
from sqlalchemy.dialects.mysql import LONGTEXT
from .database import Base
from sqlalchemy.sql import func
import arrow


class test1(Base):
    __tablename__ = "tTest"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(200))
    theType = Column(String(200))
    

注意这个表的名字,之后会是个

天坑

都创建完了,就该走alembic那一套流程了,随便百度一下都可以搜的到。
这时候如果你在写models.py的时候不注意下面这个命名的话:

__tablename__="tTest"

修改了模型结构,比如随便加一行:

# models.py
from sqlalchemy import Column, Integer, String, TIMESTAMP, Boolean, Float, TEXT
from sqlalchemy.dialects.mysql import LONGTEXT
from .database import Base
from sqlalchemy.sql import func
import arrow


class test1(Base):
    __tablename__ = "tTest"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(200))
    theType = Column(String(200))
    test = Column(String(200))

alembic revision --autogenerate -m “test3”

生成迁移就会是这样:

INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'tTest'
INFO  [alembic.autogenerate.compare] Detected added index 'ix_tTest_id' on '['id']'
G:\xxxxxxxxx\API\alembic\versions\e82962d2959c_test3.py ...  done

你会发现,你之前创建过的表tTest这里又创建了一遍,然后再迁移

alembic upgrade head

就开是疯狂报错了:

(python36) G:xxxxxxxxx\API>alembic upgrade head
INFO  [alembic.runtime.migration] Context impl MySQLImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade 158eae39a112 -> e82962d2959c, test3
.........
.........(中间还有好多省略了)
[SQL:
CREATE TABLE tTest(
        id INTEGER NOT NULL AUTO_INCREMENT, 
    	name VARCHAR(200),
    	theType VARCHAR(200)test VARCHAR(200)
)

]
(Background on this error at: http://sqlalche.me/e/f405)

就是怎么都找不到毛病

原因是表的名字不能使用驼峰法来命名

因为不同的数据库,操作系统,不一定都兼容大写,比如数据库,使用驼峰法命名表名,会全部统一成小写
作者本人并不了解alembic具体内部是通过怎样的原理自动生成迁移文件的,个人看法是,生成迁移文件时会比对你models.py中的

__tablename__="tTest"

和数据库的表名做对比,如果表名字和数据库的一摸一样,就认为是修改操作,如果不一样就认为是新建设操作,然而,如果使用驼峰命名,它判断的时候是不一样的,就给你生成建表迁移文件,然后,迁移的时候,生成的sql语句的表名是一样的,所以执行迁移的时候就会报错,大概意思就是数据表已经存在,创建表语句执行失败,后面就是一大堆的error,结果就是迁移失败
你可以修改成这样:

__tablename__="t_test"
或者
__tablename__="ttest"

反正就是不要用驼峰法
这是第一个坑

第二个坑就是再配置alembic.ini这个文件的时候

这个不一定都适用,主要原因也没想明白,在配置alembic.ini,大部分人都会在配置这个配置项:

# version location specification; this defaults
# to alembic/versions.  When using multiple version
# directories, initial revisions must be specified with --version-path
# version_locations = %(here)s/bar %(here)s/bat alembic/versions

# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8

sqlalchemy.url = mysql+mysqlconnector://用户名:密码@数据库地址:3306/数据库名

会直接复制models.py中数据库的连接设置,这样有的时候也会导致上面说的那种问题,主要原因也没想明白,之后修改成这样:

# version location specification; this defaults
# to alembic/versions.  When using multiple version
# directories, initial revisions must be specified with --version-path
# version_locations = %(here)s/bar %(here)s/bat alembic/versions

# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8

# sqlalchemy.url = mysql+mysqlconnector://用户名:密码@数据库地址:3306/数据库名
sqlalchemy.url = mysql+pymysql://用户名:密码@数据库地址:3306/数据库名

问题就莫名其妙的消失了,具体原因也不明白。。。。。之后再想把,先把任务完成。。。。。。

那个,写文章只是为了记录之前的错误,让自己以后少犯错误,如果有什么不对的地方,请各位大佬指正,就不要喷脸骂人了,谢谢~

还有,本文章不拒绝转载但是要转载的话还请告知本人,谢谢大佬。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用python中的pymsql完成如下:表结构与数据创建 1. 建立 `users` 表和 `orders` 表。 `users` 表有用户ID、用户名、年龄字段,(id,name,age) `orders` 表有订单ID、订单日期、订单金额,用户id字段。(id,order_date,amount,user_id) 2 两表的id作为主键,`orders` 表用户id为users的外键 3 插入数据 `users` (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28); `orders` (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4); 查询语句 1. 查询订单总金额 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 3. 查询订单总数最多的用户的姓名和订单总数。 4. 查询所有不重复的年龄。 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 8. 查询订单总金额最大的用户的姓名和订单总金额。 9. 查询订单总金额最小的用户的姓名和订单总金额。 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值