flask_sqlalchemy以及flask_script还有 flask_migrate
flask _script
这里是功能扩展,有sqlalchemy_script插件,可以帮我们自定制命令,使用script的时候就不用在app.run了,去到terminal里面输入指令python manage.py runserver 就能把程序启动起来,就像我们的django一样,
这里的script就是把我们的runserver的指令改成我们自定义的,下图所示,它使用场景是自定义运行脚本
这里有梗概点进来
有更详细的博客介绍戳这里
我们的flask_script需要基于蓝图来实现
代码在这里:
这里是views视图里面的py文件
from flask import blueprints xxx=blueprints.Blueprint('xxx',__name__) @xxx.route('/index',methods=['GET','POST']) def index(): return 'in me the tiger'
下面是manage.py文件也就是启动文件
from sqlalchemy_script import create_app from flask_script import Manager aps=create_app() manag=Manager(aps) @manag.command def costo(obj): print(obj) if __name__ == '__main__': manag.run()
init文件
from flask import Flask from .views.accou import xxx def create_app(): app = Flask(__name__) app.register_blueprint(xxx) return app
我们把flask和sqlalchemy数据库结合起来使用
按照老师笔记里面的步骤一步一步来做
先把蓝图的目录结构给创建出来,
1,在init文件里面创建db对象
from flask import Flask from flask_sqlalchemy import SQLAlchemy # 包含了跟sqlalchemy相关的所有操作 db = SQLAlchemy() def create_aps(): aps = Flask(__name__) aps.config.from_object('settings.DevelopmentConfig') from .views.account import ac # 这里是把我们的蓝图导入 aps.register_blueprint(ac) # 然后通过蓝图去注册app db.init_app(aps) # 2.在init里面把我们的app给传入到db中去 return aps
3.写配置文件,在settings文件中写好配置项
class BaseConfig(): SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:123@127.0.0.1:3306/book_list?charset=utf8' SQLALCHEMY_POOL_SIZE = 5 SQLALCHEMY_POOL_TIMEOUT = 30 SQLALCHEMY_POOL_RECYCLE = -1 # 追踪对象的修改并且发送信号 SQLALCHEMY_TRACK_MODIFICATIONS = False class ProductionConfig(BaseConfig): ... class DevelopmentConfig(BaseConfig): ... class TestingConfig(BaseConfig): ...
4.在model里面把表格给定义好
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String from sqlalchemy_flask import db from sqlalchemy import create_engine # Base = declarative_base() class Actors(db.Model): __tablename__ = 'actors' id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(32), nullable=True, unique=True) class Name(db.Model): __tablename__ = 'name' id = Column(Integer, primary_key=True, autoincrement=True) cname = Column(String(32), nullable=True, unique=True)
5.创建数据库表,我们用离线脚本实现这个功能,
""" web运行时,flask程序运行起来, 用户通过浏览器访问离线脚本,自定义的一个py文件+使用flask中定义好的功能 这里的主要功能就是帮我们的程序来创建或者是删除model表,我们如果不用这个离线脚本的话就用我们之前写好的model里面的代码一样可以达到效果, 就是把类创建好,然后把drop和init方法都定义好,执行当前py文件来创建或者是删除表格, 我们在这里用离线脚本就是为了节省代码,我们想用flask里面的内置方法去实现我们的功能,就需要在这里用离线脚本把源码里面封装的方法给调用上 """ from sqlalchemy_flask import db from sqlalchemy_flask import create_aps # from sqlalchemy_flask import model app = create_aps() with app.app_context(): # db.drop_all() db.create_all() # 这里是离线脚本在运行,我们的model里面的写的code_first都是继承了db.Model里面封装的方法,所以我们在这里调用 # db里面的create_all()或者是drop_all()方法都是在我们的db里面封装好的,所以我们在这里执行db.create_all()方法就会把 # 我们的model里面的code_first类都用orm给创建好数据库中的表了,他们之间的关联是在这里建立的, # 用我们的db这个sqlalchemy类实例化出来的对象来建立的 # ret = db.session.query(model.Actors).all() # print(ret)
6,在视图中使用sqlalchemy操作数据库
from flask import blueprints from sqlalchemy_flask import model from sqlalchemy_flask import db ac = blueprints.Blueprint('ac', __name__) @ac.route('/login', methods=['GET', 'POST']) def login(): data = db.session.query(model.Actors).all() obj=db.session.query(model.Name).all() print(data,obj) db.session.remove() return 'hello from other world'
最后在manage里面
from sqlalchemy_flask import create_aps from flask_script import Manager qqx = create_aps() manager = Manager(qqx) @manager.command def custom(arg): """ 自定义命令,就是我们在执行runserver的时候可以把这个runserver给替换掉, 执行我们自己的在这里自定义的命令,这里就是 python manage.py custom 28 就能启动程序了,custom是我们的函数名,我们函数以什么名字定义这里就是什么指令去执行任务 :param arg: :return: """ print(arg) @manager.option('-n', '--name', dest='nam') @manager.option('-u', '--url', dest='url') def cmd(nam, url): """ 自定义命令 执行:python manage.py cmd -n peter -u http://www.sogo.com python manage.py cmd --name wusir --url http://www.tmall.com :param name: :param url: :return: """ print(nam, url) if __name__ == '__main__': manager.run()
flask_migrate操作
这里代码比较简单,就是我们的manage.py里面的一些简单配置
from flask_migrate import Migrate, MigrateCommand app = create_app() manage = Manager(app) """ 我们在下面使用了flask-migrate组件,就不需要再用我们的离线脚本了, 它就相当于我们django里面的那个makemigration和migrate两个命令, 对于数据库进行监测更新的, 数据库迁移命名 python manage.py db init python manage.py db migrate # makemigrations python manage.py db upgrade # migrate """ Migrate(app, db) # 这个Migrate一个它记录一个库的信息,如果需要用到多个库就需要多个与之匹配 manage.add_command('db', MigrateCommand)
其他的就按照正常的逻辑去处理即可,包括文件的目录都不需要改变,不影响这里的参数配置,它只是检测我们的model文件里面的数据库表结构而已,
我们在执行python manage.py db init的时候会自动在数据库里面生成一个文件夹migrations,用来记录我们的数据库中的表的变化,我们用这个命令生成数据库表,在数据库中也会有alembic_version这个表的生成,它记录我们数据中的表的变化
我们的表每一次变更都需要在migrations文档里面去找version文档里面匹配我们所变更的数据库表里面的version_num数值一致,就能确认是谁发生了变化,然后把变更的结果重新写入到文件里面,达到检测的效果
sqlalchemy建多对多关联表,
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, String, Integer, ForeignKey, Table from sqlalchemy import create_engine from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm import relationship Base = declarative_base() # class Course2Teacher(Base): # 这里是wusir博客里面的建表方法,有错误, # __tablename__ = 'course2teacher' # # id = Column(Integer, primary_key=True, autoincrement=True) # course_id = Column(ForeignKey("course_first.id")) # teacher_id = Column(ForeignKey("teacher_first.id"))
"""多对多关联的时候是需要手动生成第三张表的"""
teacher_classes = Table(
"course2teacher", Base.metadata,
Column("teacher_id", Integer, ForeignKey("teacher_first.id"), nullable=False, primary_key=True),
Column("course_id", Integer, ForeignKey("course_first.id"), nullable=False, primary_key=True)
)
class Course(Base):
__tablename__ = 'course_first'
id = Column(Integer, primary_key=True)
name = Column(String(32))
teacher = relationship("Teacher", secondary="course2teacher", backref='course')
class Teacher(Base):
__tablename__ = 'teacher_first'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32))
class Student(Base):
__tablename__ = 'student_first'
id = Column(Integer, primary_key=True)
name = Column(String(32), index=True, nullable=False)
course_id = Column(Integer, ForeignKey("course_first.id"))
course = relationship("Course", backref='st_course')
def init_db():
engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/test?charset=utf8", max_overflow=0, pool_size=5, pool_timeout=30, pool_recycle=-1)
Base.metadata.create_all(engine)
if __name__ == '__main__':
init_db()