学习狗书flask web更新了model.py后使用数据库迁移flask migrate+flask upgrade,竟然删除了我的所有表

昨天学到博客用户增加重设密码的功能,给User表加了两个方法后,按照往常一样进行数据库迁移:运行两个指令flask migrate,flask upgrade。然后美滋滋地输入测试指令:flask test,却报错说找不到User表。
我一看数据库,确实表都没了,部分报错信息:

(venv) E:\program\Python\Web\MySecondFlaskApp>flask test
test_app_exists (test_basics.BasicsTestCase) ... ok
test_app_is_testing (test_basics.BasicsTestCase) ... ok
test_expired_confirmation_token (test_user_model.UserModelTestCase) ... ERROR
test_invalid_confirmation_token (test_user_model.UserModelTestCase) ... ERROR
test_invalid_reset_token (test_user_model.UserModelTestCase) ... ERROR
test_no_password_getter (test_user_model.UserModelTestCase) ... ok
test_password_salts_are_random (test_user_model.UserModelTestCase) ... ok
test_password_setter (test_user_model.UserModelTestCase) ... ok
test_password_verification (test_user_model.UserModelTestCase) ... ok
test_valid_confirmation_token (test_user_model.UserModelTestCase) ... ERROR
test_valid_reset_token (test_user_model.UserModelTestCase) ... ERROR

======================================================================
ERROR: test_expired_confirmation_token (test_user_model.UserModelTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "e:\program\python\web\mysecondflaskapp\venv\lib\site-packages\sqlalchemy\engine\base.py", line 1965, in _exec_single_context
    cursor, str_statement, effective_parameters, context
  File "e:\program\python\web\mysecondflaskapp\venv\lib\site-packages\sqlalchemy\engine\default.py", line 748, in do_execute
    cursor.execute(statement, parameters)
sqlite3.OperationalError: no such table: users

我看了一下ERROR的这些测试函数,都是在db.session.commit()处开始出错。
我的表怎么会被删了?
在Stack Overflow上一番搜寻,很快找到了答案:
flask migrate seemed to delete all my database data
迁移脚本中还没有同步得到任何表,迁移脚本是空的,用空的脚本去flask upgrade 数据库,自然就相当于把数据库的表给删了。
解决方法:在flasky.py内加上app上下文

# Import database models with app context
with app.app_context():
    from app.models import User, Role

migrate = Migrate(app, db)

然后迁移数据库(flask migrate+ flask upgrade),出现了新的迁移脚本并且不是空的。(之前几次迁移数据库,都没产生新的迁移脚本,我竟然没怀疑有问题!!!)
查看数据库data.sqlite,里面有User等表的结构了。

但是再flask test进行单元测试,还是报同样的错???我一看数据库,又空了
仔细看一遍书上《使用Flask-Migrate实现数据库迁移》这章节,发现了一个之前漏掉的知识点:每次flask upgrade后会生成的新的data.sqlite。也就是说我可以随便删除它,只要迁移脚本还在就行。用flask upgrade指令,根据最新的迁移脚本来生成数据库。

删除data.sqlite后,用flask upgrade,确实生成了一个完整表结构的数据库。但是每次单元测试后,数据库里面的User等表又没了。单元测试怎么会删我的表呢?

最后一番搜索,在Stack Overflow上找到了跟我遇到一样问题的人,但是导致问题的原因不一样:
How to setup testing script in Flask with SQLite?
他是SQLALCHEMY_DATABASE_URI这个参数名写错了。

那我是因为啥?为什么flask test 会把迁移过来的数据库弄空?
flask test 单元测试自己的数据库呢?我并没有给单元测试分配数据库,它会跟数据迁移一样自动生成吗?每次flask upgrade后会生成的新的数据库,这时的表结构是没问题的,但是单元测试后,直接没表了。
想了半天,找到了答案。就是我因为偷懒,在config.py 里面把 DevelopmentConfig和TestingConfig的数据库设置成同一个了!我以为只要我不手动更改,就一直会运行默认的 DevelopmentConfig

config = {
    'development': DevelopmentConfig,
    'testing': TestingConfig,
    'production': ProductionConfig,

    'default': DevelopmentConfig   # 默认设置的这个!
}

然而事实上,运行单元测试,是用的TestingConfig的配置!!!
正确的应该是用两个不同的名字,比如data-dev.sqlitedata-test.sqlite,而不是都用data.sqlite!!!

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite')


class TestingConfig(Config):
    TESTING = True  # True默认不发送邮件
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data-test.sqlite')

运行数据库迁移指令(flask migrate+ flask upgrade),生成了data-dev.sqlite
然后运行单元测试指令flask test,生成了data-test.sqlite
在这里插入图片描述

现在就能解释得通一切了。

数据库迁移后生成的data.sqlite没错,里面的表也是完整存在的。单元测试运行后,新生成的数据库也叫data.sqlite,把原来有表的数据库给覆盖了。由于是在测试脚本中,生成表后会再删除(测试脚本中setUp,tearDown函数),所以直观上来看好像是“同一个数据库,但是表被删了”。

现在再来运行,都测试成功!

(venv) E:\program\Python\Web\MySecondFlaskApp>flask test
test_app_exists (test_basics.BasicsTestCase) ... ok
test_app_is_testing (test_basics.BasicsTestCase) ... ok
test_expired_confirmation_token (test_user_model.UserModelTestCase) ... ok
test_invalid_confirmation_token (test_user_model.UserModelTestCase) ... ok
test_invalid_reset_token (test_user_model.UserModelTestCase) ... ok
test_no_password_getter (test_user_model.UserModelTestCase) ... ok
test_password_salts_are_random (test_user_model.UserModelTestCase) ... ok
test_password_setter (test_user_model.UserModelTestCase) ... ok
test_password_verification (test_user_model.UserModelTestCase) ... ok
test_valid_confirmation_token (test_user_model.UserModelTestCase) ... ok
test_valid_reset_token (test_user_model.UserModelTestCase) ... ok

----------------------------------------------------------------------
Ran 11 tests in 9.176s

OK


总结:flask migrate 指令“删了”我的数据库的表,flask test 也 “删了”我的表
对config.py的结构 和 flask_migrate的原理有了更深的认知。
每次flask migrate之后,一定要检查新生成的迁移脚本内有没有问题,没有问题再flask upgrade更新,否则会出现数据丢失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值