Python中使用sqlalchemy插件能够实现ORM(Object Relationship Mapping,模型关系映射)框架,而Flask中的flask-sqlalchemy其实就是在sqlalchemy外进行了一层封装,使得在flask中使用起来更加方便,固然sqlalchemy的原有的方法也均可以使用。也就是说sqlalchemy在普通的Python程序中也可使用,而flask-sqlalchemy是为flask“定制”的。python
我这里使用的是MySQL数据库,Python3中对应的驱动插件为pymysql(Python2中对应的驱动插件为mysql-python),因此这里的数据库操做须要安装MySQL、pymysql(或mysql-python)和flask-sqlalchemy。mysql
1、MySQL数据库安装(其实MySQL的东西网上一大推)sql
安装版:exe安装版按照步骤一步步来就好了,能够只安装MySQL服务便可,若是电脑上没有对应版本VS C++也会提示你安装的。数据库
免安装版/解压版:根据如下步骤进行便可:flask
[mysqld]
basedir=D:\MySQL Server 8.0
datadir=D:\MySQL Server 8.0\datasession
注:解压后能够本身更改文件夹名称,好比我这儿是“MySQL Server 8.0”,配置这两个信息后,其中的“data”文件夹不要本身建立(默认是没有这个文件夹的,可是会在下一步自动建立),不然MySQL服务会启动失败。app
安装和使用过程当中遇到的问题和解决方案:框架
2、数据库驱动插件安装(pymysql/mysql-python)ide
3、SQLAlchemy使用函数
1.安装:pip install sqlalchemy
2.链接数据库:设置数据库链接字符串,并使用create_engine函数建立一个engine对象,并使用engine对象的connect方法链接数据库,注意链接数据库后须要使用close方法关闭链接。
from sqlalchemy import create_engine # 数据库链接信息 HOSTNAME = '127.0.0.1' # 本机地址 PORT = '3306' # MySQL默认端口 DATABASE = 'sqlalchemy_demo' # 数据库名 USERNAME = 'root' # 安装数据库时设置的用户名和密码 PASSWORD = '123456' # 数据库链接字符串 # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) # 建立一个engine对象 engine = create_engine(DB_URI) # 链接数据库 conn = engine.connect() # 执行SQL语句,并返回执行结果 sel_res = conn.execute('select * from User') # 获取并打印一条查询结果 print(sel_res.fetchone()) # 关闭链接 conn.close()
3.定义模型类:使用declarative_base函数生成一个模型类的基类,以便模型类映射到数据库中,且必须使用__tablename__指定表名(一个类对应数据库中一张表,不一样的类实例对应表中不一样的记录)。
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base # 数据库链接信息 HOSTNAME = '127.0.0.1' PORT = '3306' DATABASE = 'sqlalchemy_demo' USERNAME = 'root' PASSWORD = '123456' # 数据库链接字符串 # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) # 建立一个engine对象 engine = create_engine(DB_URI) # 建立全部模型类的基类 Base = declarative_base(engine) # 注意如下定义全是在类中直接进行的,没有在__init__等方法中进行 class Person(Base): # 使用__table__name指定表名 __tablename__ = 'person' # 定义属性字段id为整型、主键、自动增加 id = Column(Integer, primary_key=True, autoincrement=True) # 定义属性字段name为最长50个字符的字符串类型,且非空 name = Column(String(50), nullable=False) # 定义属性字段age为整型 age = Column(Integer) # 删除表,不用特意指定表,在加载Python文件时会自动检查定义了哪些表,并删除这些表 Base.metadata.drop_all() # 将全部模型映射到数据库中,而且相同的模型类只在第一次执行时会生效,即若是第一次执行后, # 又对类进行了修改,从新运行程序执行metadata.create_all()后并不会把更新的内容映射到数据库中,前提是数据库中的表没有被删除 Base.metadata.create_all()
4.经常使用数据类型:数据类型对应的类直接从模块sqlalchemy中导入便可。
5.Column经常使用参数:Column的第一个参数name用来指定数据中的属性名,若是不指定则默认为该属性变量名为属性名。
6.增删改查操做:使用sessionmaker建立session,并在session中进行增删改查操做,注意若是涉及到修改数据库,必定要commit后才能在数据库生效。
增删改查简单示例(数据库链接代码和模型类代码见前面的代码示例):
from sqlalchemy import create_engine, Column, Integer, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker engine = create_engine(DB_URI) # 别忘了实例化后再一次调用(加括号),会调用类的__call__生成session session = sessionmaker(engine)() # 增长数据 def add_data(): p = Person(name='Jason', age=19) # 添加一条数据到内存中 session.add(p) # 添加多条数据到内存中 p1 = Person(name='Mickle', age=20) p2 = Person(name='Marya', age=21) session.add_all([p1, p2]) # 提交到数据库中 session.commit() # 删除数据 def del_data(): p = session.query(Person).first() # 直接删除提交便可 session.delete(p) session.commit() # 修改数据 def update_data(): p = session.query(Person).first() # 获取对象后,直接修改提交便可 p.name = 'JiuyunnZhao' session.commit() # 查询数据 def search_data(): # 查找模型类对应表的的全部数据(可用for遍历) # persons = session.query(Person).all() # 查询知足某个条件的全部数据(可for遍历),查询条件只有参数和一个等号(这种方式比较简单,由于只针对一个类) # persons = session.query(Person).filter_by(name='Mickle').all() # 查询知足某个条件的全部数据(可for遍历),查询条件类名.参数和双等号(filter中的条件能够更加复杂,这里只是简单举例) # persons = session.query(Person).filter(Person.name == 'Mickle').all() # for p in persons: # print(p) # 根据主键查询某一条数据,没有对应的主键则返回None # p = session.query(Person).get(100) # 获取某张表的第一条数据 p = session.query(Person).first() p = session.query(Person).filter(Person.name == 'Mickle').first() p = session.query(Person).filter_by(name='Mickle').first() print(p) # 测试代码 if __name__ == '__main__': add_data() # del_data() # update_data() # search_data()
7.聚合函数:从sqlalchemy中导入func,func中有许多聚合函数可使用。其实func中没有“真正”的聚合函数,都是MySQL中的函数,也就是或MySQL中的聚合函数均可以在func中找到和使用。
8.filter中的条件过滤(注意不是filter_by方法):
9.外键及外键约束:在想要定义为外键的列中传入参数ForeignKey('tablename.column_name')便可,若是想要定义外键约束,在ForeignKey中指定参数ondelete为相应约束便可,默认约束为RESTRICT。
from sqlalchemy import create_engine, Column, Integer, String, Text, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker HOSTNAME = '127.0.0.1' PORT = '3306' DATABASE = 'sqlalchemy_demo' USERNAME = 'root' PASSWORD = '123456' # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) engine = create_engine(DB_URI) Base = declarative_base(engine) # 父表 class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) # 子表 class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外键列,意为一个用户能够有多篇文章,注意此列的类型应该对应父表的主键类型一致
# 注意这里是“表名.属性名”,而不是“类名.属性变量名” user_id = Column(Integer, ForeignKey('user.user_id', ondelete='CASCADE'))
10.外键关系:经过relationship将两个存在外键关联的两张表创建一个关系属性,并经过这个属性去进行互相访问。
一对一关系简单示例:
# 一对一关系示例1:一张表定义外键,另外一张表定义一对一关系,即uselist=False class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) # 添加一个到模型Article的一对一关系,关键在于uselist=False,由于默认是True,那就是一对多了 article = relationship('Article', uselist=False) class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外键列“表名.属性名”,而不是“类名.属性变量名” user_id = Column(Integer, ForeignKey('user.user_id')) # 添加一个到模型User的关系,因为User类中定义了一对一uselist=False,因此这个关系天然也是一对一了,也不用再指定uselist=False author = relationship('User') # 一对一示例2:利用反向引用函数backref创建一对一关系 # backref函数中的参数和relationship中的参数是一致的,relationship中可用的参数它均可以用 from sqlalchemy.orm import sessionmaker, relationship, backref class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外键列 user_id = Column(Integer, ForeignKey('user.user_id')) # 这里backref的使用至关于在User类中创建了一个名为article的关系,且参数uselist为False author = relationship('User', backref=backref('article', uselist=False))
一对多关系简单示例
# 一对多关系示例1 class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) # 添加一个到模型Article的关系,一对多,表示“多”的的变量articles其实继承自list,因此append等方法也适用这个属性 articles = relationship('Article') class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外键列,注意这里是“表名.属性名”,而不是“类名.属性变量名” user_id = Column(Integer, ForeignKey('user.user_id')) # 添加一个到模型User的关系,多对一 author = relationship('User') # 一对多关系示例2 class User(Base): __tablename__ = 'user' user_id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) class Article(Base): __tablename__ = 'article' atc_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) content = Column(Text, nullable=False) # 外键列,注意这里是“表名.属性名”,而不是“类名.属性变量名” user_id = Column(Integer, ForeignKey('user.user_id')) # 反向引用,backref参数就至关于自动给User模型添加了一个名为articles且关联到User模型的的关系 author = relationship('User', backref='articles') # 使用示例,如下代码将在article表中添加两条数据 user =User(username='Mickle') article1 = Article(title='aaa', content='1111') article2 = Article(title='bbb', content='222') user.articles.append(article1) user.articles.append(article2) session.add(user) session.commit()
多对多关系简单示例
# 多对多关系示例:一篇文章能够有多个标签,一个标签也能够用于多篇文章 from sqlalchemy import create_engine, Column, Integer, String, Text, ForeignKey, Table from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship HOSTNAME = '127.0.0.1' PORT = '3306' DATABASE = 'sqlalchemy_demo' USERNAME = 'root' PASSWORD = '123456' # dialect+driver://username:password@host:port/database DB_URI = 'mysql+pymysql://{username}:{password}@{host}:{port}/{database}'.format( username=USERNAME, password=PASSWORD, host=HOSTNAME, port=PORT, database=DATABASE ) engine = create_engine(DB_URI) Base = declarative_base(engine) session = sessionmaker(engine)() class Article(Base): __tablename__ = 'article' artcle_id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) # 与Tag创建关联关系和反向引用关系,并指明中间表为article_tag # 这个关系能够定义在关联的两张表中的任意一张表中均可以 tags = relationship('Tag', backref='articles', secondary=article_tag) class Tag(Base): __tablename__ = 'tag' tag_id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(50), nullable=False) # 经过类Table来生成一个中间表 article_tag = Table( 'article_tag', # 表名 Base.metadata, # 继承的模型类型 # 定义中间表中的列,声明此列关联到表article的列article_id,并指明以此列来做为复合主键的其中一列 Column('article_id', Integer, ForeignKey('article.article_id'), primary_key=True), # 定义中间表中的列,声明此列关联到表tag的列tag_id,并指明以此列来做为复合主键的其中一列 Column('tag_id', Integer, ForeignKey('tag.tag_id'), primary_key=True) ) # 添加数据到数据库中 article1 = Article(title='my article 1') article2 = Article(title='my article 2') tag1 = Tag(name='my tag 1') tag2 = Tag(name='my tag 2') article1.tags.append(tag1) article1.tags.append(tag2) article2.tags.append(tag1) article2.tags.append(tag2) session.add(article1) session.add(article2) session.commit()
11.查询排序:默认升序,降序通常使用对应属性的desc()方法便可。
升序降序简单示例:
# 如下列子以模型类Article中的字段create_time做为示例(字符串中的属性名是数据库中的属性名而不是变量名(没有定义时二者是同样的)) # 方式一:在session中使用order_by查询排序 # 升序 articles = session.query(Article).order_by(Article.create_time).all() articles = session.query(Article).order_by('create_time').all() # 降序) articles = session.query(Article).order_by(Article.create_time.desc()).all() articles = session.query(Article).order_by('-create_time').all() # 方式2、在模型类中使用__mapper_args__的order_by指定查询排序 class Article(Base): __tablename__ = 'article' id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) create_time = Column(DateTime, nullable=False, default=datetime.now) __mapper_args__ = { 'order_by': create_time, # 升序 # 'order_by': create_time.desc(), # 降序 } # 方式3、使用模型类中relationship的roder_by进行指定查询排序 class User(Base): __tablename__ = 'user' id = Column(Integer, primary_key=True, autoincrement=True) username = Column(String(50), nullable=False) class Article(Base): __tablename__ = 'article' id = Column(Integer, primary_key=True, autoincrement=True) title = Column(String(50), nullable=False) create_time = Column(DateTime, nullable=False, default=datetime.now) user_id = Column(Integer, ForeignKey('user.id')) author = realtionship('User', backref=backref('articles', order_by=create_time)) # 升序 # author = realtionship('User', backref=backref('articles', order_by=create_time.desc())) # 降序
12.query对象经常使用方法:
13.高级查询:
4、Flask-SQLAlchemy使用
因为Flask-SQLAlchemy实际上是SQLAlchemy在外面进行了一层封装,以便更好的适用于flask,因此Flask-SQLAlchemy和SQLAlchemy在使用上除了最外层封装的定义外都是同样的,下面只讲一些常须要注意的不一样之处
安装:pip install flask-sqlalchemy
1. 配置:须要在配置文件中配置数据库链接字符串“SQLALCHEMY_DATABASE_URI”,其中driver为Python2的mysqldb,Python3的pymysql,具体以安装的插件为准。
# 数据库链接固定格式格式字符串 # dialect+driver://username:password@host:port/database DIALECT = 'mysql' DRIVER = 'mysqldb' USERNAME = 'root' PASSWORD = 123456 HOST = '127.0.0.1' PORT = '3306' DATABASE = 'db_demo1' SQLALCHEMY_DATABASE_URI = '{dialect}+{driver}://{username}:{password}@{host}:{port}/{database}?charset=utf8'.format( dialect=DIALECT, driver=DRIVER, username=USERNAME, password=PASSWORD, host=HOST, port=PORT, database=DATABASE )
2.使用:Column、relationship等均可以直接在“from flask_sqlalchemy import SQLAlchemy”的SQLAlchemy实例中直接使用
简单示例(配置信息写在了配置文件config.py中了)
from flask import Flask from flask_sqlalchemy import SQLAlchemy import config app = Flask(__name__) app.config.from_object(config) db = SQLAlchemy(app) db.create_all() class User(db.Model): __tablename__ = 'user' # 设置表名,未设置则以类名全小写为表名 id = db.Column(db.Integer, primary_key=True, autoincrement=True) # 定义列id,整型,主键,自增加 username = db.Column(db.String(100), nullable=False) # 定义列username,字符型(最大100个字符),非空