flask-sqlalchemy和pipreqs
flask-sqlalchemy
sqlalchemy本身和flask没有任何关系,flask-sqlalchemy是flask的一个第三方组件,这个组件做的事情就是让使用sqlalchemy更加方便一点,但是其内部本质还是sqlalchemy
安装:pip3 install flask-sqlalchemy
flask的项目目录
下面来详细看一下我这目录
model.py
flask_app目录下的__init__.py
其中create_table.py这个离线脚本用来创建数据表,因为 db.create_all() 需要连接数据库做操作,连接需要读取app.config中的配置,单独的离线脚本执行和app没有半毛钱关系,所以需要用到
应用上下文,应用上下文中有app和g,其中app.config又是db连接数据库需要的。从这里就可以看出,为啥flask把上下文分成请求上下文和应用上下文了,比如说我们这里只用到了应用上下文的内容,
如果把请求上下文和应用上下文合成一个联合上下文,那么我们要想使用上下文的app的使用还要构造请求对象以构建一个这样的联合上下文。我们发现虽然执行了这个脚本,数据库的表依旧没有创建成功。
这又是为什么呢?因为想要离线脚本db帮我们创建表,首先db需要在内存中找到继承db.Model的类,但是就执行这个离线脚本而言,内存中根本找不到继承自db.Model的类,所以我们在from flask_app import db,create_app
执行flask_app的__init__.py的时候把类加载到内存
from flask_app import db,create_app
app = create_app()
app_ctx = app.app_context() # app_ctx = app/g
with app_ctx: # __enter__,通过LocalStack放入Local中
db.create_all() # 调用LocalStack放入Local中获取app,再去app中获取配置
注意一点:from flask_app import models
models是一个py文件,执行这条导入命令不仅会执行flask_app包的__init__.py,还会执行model.py的内容,原先一直以为不会执行model.py,只执行flask_app包的__init__.py
pipreqs
如果有这样一个场景:公司老大给你一个python写的程序,但是里面没有requirement.txt,那我想要运行这个程序,肯定需要安装这个程序的所有第三方包,并且版本最好能对的上。那么怎么办呢?去问老大?老大可能没空理你,那难道需要自己去每个py文件看导入然后再去pip安装吗,那包的版本问题怎么解决呢?pipreqs这个模块能帮我们解决这类问题
安装:pip3 install pipreqs
在项目根目录使用:pipreqs ./ --encoding='utf-8'
这样根目录就会生成一个requirements.txt文件
此时应该配合虚拟环境来使用,因为这个程序的包的版本可能和系统的不一样
安装虚拟环境:pip3 install virtualenv --no-site-packages
创建一个目录专门用来存放虚拟环境,创建虚拟环境:virtualenv env1
, 进入虚拟环境: env1目录下scripts目录下的activate,退出虚拟环境:env1目录下scripts目录下的deactivate
flask-script
flask-script 这个第三方组件可以帮我们完成修改sqlalchemy的表的结构
from flask_app import create_app
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from flask_app import db
app = create_app()
manager = Manager(app)
Migrate(app, db)
# MigrateCommand 是一个Command对象
manager.add_command('db', MigrateCommand)
# 函数名test和上面的'db'一样
# python3 manage.py test -n=jack 或者 python3 manage.py test -n jack
@manager.option('-n', '--name', dest='name')
def test(name, url):
print(name, url)
if __name__ == '__main__':
manager.run()