Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate

上一篇文章>Flask入门(三)之信号、MetaClass、Session、WTForms

一、SQLAlchemy


目标:类/对象操作 -> SQL -> pymysql、MySQLdb -> 数据库中执行

1、SQLAlchemy组成

(1)组成
  • Engine:框架的引擎
  • Connection Pooling :数据库连接池
  • Dialect:选择连接数据库的DB API种类
  • Schema/Types:架构和类型
  • SQL Exprression Language:SQL表达式语言
(2)数据库API
MySQL-Python:
	mysql+mysqldb://:@[:]/
pymysql:
	mysql+pymysql://:@/[?]
MySQL-Connector:
	mysql+mysqlconnector://:@[:]/
cx_Oracle:
	oracle+cx_oracle://user:pass@host:port/dbname[?key=value&key=value...]

2、SQLAlchemy安装

下载地址:https://pypi.org/project/SQLAlchemy/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/55/98/56b7155bab287cd0c78dee26258835db36e91f2efef41f125ed6f6f1f334/SQLAlchemy-1.3.6.tar.gz
[root@Python ~]# tar xf SQLAlchemy-1.3.6.tar.gz
[root@Python ~]# cd SQLAlchemy-1.3.6/
[root@Python SQLAlchemy-1.3.6]# python setup.py install

3、基本使用

(1)执行原生SQL

只用连接池功能

<1>方式一

from sqlalchemy import create_engine
engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/databasename?charset=utf8",
    max_overflow=0,         ###超过连接池大小外最多创建的链接
    pool_size=5,            ###连接池大小
    pool_timeout=30,        ###池中没有线程最多等待的时间,否则报错
    pool_recycle=-1,        ###多久之后对线程池中的线程呢个进行一次链接的回收(重置)
)

conn = engine.raw_connection()
cursor = conn.cursor()
cursor.execute(
    "select * from tablename"
)
result = cursor.fetchall()
cursor.close()
conn.close()

<2> 方式二

#!/usr/bin/env python
#coding:utf-8
import threading
from sqlalchemy import create_engine
engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/databasename?charset=utf8",
    max_overflow=0,         ###超过连接池大小外最多创建的链接
    pool_size=5,            ###连接池大小
    pool_timeout=30,        ###池中没有线程最多等待的时间,否则报错
    pool_recycle=-1,        ###多久之后对线程池中的线程呢个进行一次链接的回收(重置)
)
def task(arg):
    conn = engine.raw_connection()
    cursor = conn.cursor()
    cursor.execute(
        "select * from tablename"
    )
    result = cursor.fetchall()
    cursor.close()
    conn.close()

for i in range(20):
    t = threading.Thread(target=task, args=(i,))
    t.start()
(2)ORM方式

<1> 配置models.py

[root@Python sqlalchemy]# vim models.py
#!/usr/bin/env python
#coding:utf-8
import datetime
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index

Base = declarative_base()

class Users(Base):
    __tablename__ = 'users'    ###数据库表名

    id = Column(Integer, primary_key=True)    ###主键
    name = Column(String(32), index=True, nullable=False)   ###不能为空

def init_db():
    engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/databasename?charset=utf8",
        max_overflow=0,  ###超过连接池大小外最多创建的链接
        pool_size=5,  ###连接池大小
        pool_timeout=30,  ###池中没有线程最多等待的时间,否则报错
        pool_recycle=-1,  ###多久之后对线程池中的线程呢个进行一次链接的回收(重置)
    )
    ### 创建表
    Base.metadata.create_all(engine)

def drop_db():
    engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/databasename?charset=utf8",
        max_overflow=0,  ###超过连接池大小外最多创建的链接
        pool_size=5,  ###连接池大小
        pool_timeout=30,  ###池中没有线程最多等待的时间,否则报错
        pool_recycle=-1,  ###多久之后对线程池中的线程呢个进行一次链接的回收(重置)
    )
    ### 删除表
    Base.metadata.drop_all(engine)

if __name__ == '__main__':
    drop_db()
    init_db()

<2> 配置app.py

[root@Python sqlalchemy]# vim app.py
#!/usr/bin/env python
#coding:utf-8
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from models import Users

engine = create_engine("mysql+pymysql://root:[email protected]:3306/databasename", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine)

### 每次执行数据库操作时,都需要创建一个session
session = Session()

############## 执行ORM操作 #############
obj1 = Users(name="dream")
session.add(obj1)

### 提交事务
session.commit()
### 关闭session
session.close()

4、增删改查

(1)配置models.py
[root@Python sqlalchemy]# vim models.py
#!/usr/bin/env python
#coding:utf-8
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import datetime
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
from sqlalchemy.orm import relationship

Base = declarative_base()

# ##################### 单表示例 #########################
class Users(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String(32), index=True)
    age = Column(Integer, default=18)
    email = Column(String(32), unique=True)
    ctime = Column(DateTime, default=datetime.datetime.now)
    extra = Column(Text, nullable=True)

    __table_args__ = (
        # UniqueConstraint('id', 'name', name='uix_id_name'),
        # Index('ix_id_name', 'name', 'extra'),
    )

class Hosts(Base):
    __tablename__ = 'hosts'

    id = Column(Integer, primary_key=True)
    name = Column(String(32), index=True)
    ctime = Column(DateTime, default=datetime.datetime.now)

###################### 一对多示例 #########################
class Hobby(Base):
    __tablename__ = 'hobby'
    id = Column(Integer, primary_key=True)
    caption = Column(String(50), default='篮球')

class Person(Base):
    __tablename__ = 'person'
    nid = Column(Integer, primary_key=True)
    name = Column(String(32), index=True, nullable=True)
    hobby_id = Column(Integer, ForeignKey("hobby.id"))

    ### 与生成表结构无关,仅用于查询方便
    # hobby = relationship("Hobby", backref='pers')

###################### 多对多示例 #########################
class Server2Group(Base):
    __tablename__ = 'server2group'
    id = Column(Integer, primary_key=True, autoincrement=True)
    server_id = Column(Integer, ForeignKey('server.id'))
    group_id = Column(Integer, ForeignKey('group.id'))

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer, primary_key=True)
    name = Column(String(64), unique=True, nullable=False)

    ### 与生成表结构无关,仅用于查询方便
    #servers = relationship('Server', secondary='server2group', backref='groups')

class Server(Base):
    __tablename__ = 'server'
    id = Column(Integer, primary_key=True, autoincrement=True)
    hostname = Column(String(64), unique=True, nullable=False)

if __name__ == '__main__':
    engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
        max_overflow=0,  # 超过连接池大小外最多创建的连接
        pool_size=5,  # 连接池大小
        pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
        pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
    )
    Base.metadata.create_all(engine)
(2)配置app.py(操作)
[root@Python sqlalchemy]# vim app.py
#!/usr/bin/env python
#coding:utf-8
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

import models

engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
    max_overflow=0,
    pool_size=5,
    pool_timeout=30,
    pool_recycle=-1,
)
Session = sessionmaker(bind=engine)

# 每次执行数据库操作时,都需要创建一个session
session = Session()

############## 增加单个 #############
# obj1 = models.Users(name="dream123", email="[email protected]")
# session.add(obj1)
# session.commit()
############## 增加多个 #############
# session.add_all([
#     models.Users(name='dream', email='[email protected]'),
#     models.Users(name='dreamya', email='[email protected]'),
# ])
# session.commit()
############## 查 #############
# user_list = session.query(models.Users).all()    ###对象,查询所有
# for row in user_list:
#     print(row.id, row.name, row.email, row.ctime)
"""
session.query(models.Users.name.label('xx'), models.Users.email).all()   ###定义Users.age别名为xx
session.query(models.Users).filter(models.Users.name == "dream").all()
session.query(models.Users).filter_by(name='dream').all()      ###查询所有name等于dream
session.query(models.Users).filter_by(name='dream').first()    ###查询第一条name等于dream
session.query(Users).filter(text("id<:value and name=:name")).params(value=224, name='xxx').order_by(models.Users.id).all()   ###valer和name为参数通过params中传入
session.query(Users).from_statement(text("SELECT * FROM users where name=:name")).params(name='ed').all()        ###原生SQL
"""
# ---------------------------
# user_list = session.query(models.Users).filter(models.Users.id > 2)  ###查询users id大于2
# for row in user_list:
#     print(row.id, row.name, row.email, row.ctime)
############## 删除 #############
# session.query(models.Users).filter(models.Users.id > 2).delete()    ###删除users id大于2
# session.commit()
############## 修改 #############
# session.query(models.Users).filter(models.Users.id > 1).update({'name': 'tony'})
# session.commit()

# 关闭session
session.close()

5、常用SQLAlchemy操作

### 条件
ret = session.query(Users).filter_by(name='dream').all()
ret = session.query(Users).filter(Users.id > 1, Users.name == 'eric').all()
ret = session.query(Users).filter(Users.id.between(1, 3), Users.name == 'eric').all()
ret = session.query(Users).filter(Users.id.in_([1,3,4])).all()
ret = session.query(Users).filter(~Users.id.in_([1,3,4])).all()
ret = session.query(Users).filter(Users.id.in_(session.query(Users.id).filter_by(name='eric'))).all()
from sqlalchemy import and_, or_
ret = session.query(Users).filter(and_(Users.id > 3, Users.name == 'eric')).all()
ret = session.query(Users).filter(or_(Users.id < 2, Users.name == 'eric')).all()
ret = session.query(Users).filter(
    or_(
        Users.id < 2,
        and_(Users.name == 'eric', Users.id > 3),
        Users.extra != ""
    )).all()

### 通配符
ret = session.query(Users).filter(Users.name.like('e%')).all()
ret = session.query(Users).filter(~Users.name.like('e%')).all()

### 限制
ret = session.query(Users)[1:2]

### 排序
ret = session.query(Users).order_by(Users.name.desc()).all()
ret = session.query(Users).order_by(Users.name.desc(), Users.id.asc()).all()

### 分组
from sqlalchemy.sql import func

ret = session.query(Users).group_by(Users.extra).all()
ret = session.query(
    func.max(Users.id),
    func.sum(Users.id),
    func.min(Users.id)).group_by(Users.name).all()

ret = session.query(
    func.max(Users.id),
    func.sum(Users.id),
    func.min(Users.id)).group_by(Users.name).having(func.min(Users.id) >2).all()

### 连表

ret = session.query(Users, Favor).filter(Users.id == Favor.nid).all()
ret = session.query(Person).join(Favor).all()
ret = session.query(Person).join(Favor, isouter=True).all()

### 组合
q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union(q2).all()

q1 = session.query(Users.name).filter(Users.id > 2)
q2 = session.query(Favor.caption).filter(Favor.nid < 2)
ret = q1.union_all(q2).all()

6、基于relationship操作ForeignKey

(1)环境准备

<1> 配置models.py

[root@Python sqlalchemy]# vim models.py
#!/usr/bin/env python
#coding:utf-8
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import datetime
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
from sqlalchemy.orm import relationship

Base = declarative_base()

###################### 一对多示例 #########################
class Hobby(Base):
    __tablename__ = 'hobby'
    id = Column(Integer, primary_key=True)
    caption = Column(String(50), default='篮球')

class Person(Base):
    __tablename__ = 'person'
    nid = Column(Integer, primary_key=True)
    name = Column(String(32), index=True, nullable=True)
    hobby_id = Column(Integer, ForeignKey("hobby.id"))

if __name__ == '__main__':
    engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
        max_overflow=0,  # 超过连接池大小外最多创建的连接
        pool_size=5,  # 连接池大小
        pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
        pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
    )
    Base.metadata.create_all(engine)

<2> 配置app.py(添加数据)

[root@Python sqlalchemy]# vim app.py
#!/usr/bin/env python
#coding:utf-8
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models

engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
    max_overflow=0,
    pool_size=5,
    pool_timeout=30,
    pool_recycle=-1,
)
Session = sessionmaker(bind=engine)
session = Session()

### 执行ORM操作
session.add_all([
    models.Hobby(caption='篮球'),
    models.Hobby(caption='足球'),
])
session.add_all([
    models.Person(name='dream', hobby_id=2),
    models.Person(name='dreamya1', hobby_id=2),
    models.Person(name='dreamya', hobby_id=1),
    models.Person(name='dream1', hobby_id=1),
])
session.commit()
### 关闭session
session.close()

<3> 查询结果

[root@Python ~]# mysql -uroot -p1
MariaDB [(none)]> use test;
MariaDB [test]> select * from hobby;
+----+---------+
| id | caption |
+----+---------+
|  1 | 篮球    |
|  2 | 足球    |
+----+---------+

MariaDB [test]> select * from person;
+-----+----------+----------+
| nid | name     | hobby_id |
+-----+----------+----------+
|   1 | dream    |        2 |
|   2 | dreamya1 |        2 |
|   3 | dreamya  |        1 |
|   4 | dream1   |        1 |
+-----+----------+----------+
(2)普通查询
[root@Python sqlalchemy]# vim app.py
#!/usr/bin/env python
#coding:utf-8
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models

engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
    max_overflow=0,
    pool_size=5,
    pool_timeout=30,
    pool_recycle=-1,
)
Session = sessionmaker(bind=engine)
session = Session()

### 执行ORM操作
# session.add_all([
#     models.Hobby(caption='篮球'),
#     models.Hobby(caption='足球'),
# ])
# session.add_all([
#     models.Person(name='dream', hobby_id=2),
#     models.Person(name='dreamya1', hobby_id=2),
#     models.Person(name='dreamya', hobby_id=1),
#     models.Person(name='dream1', hobby_id=1),
# ])
# session.commit()
# person_list = session.query(models.Person).all()
# for row in person_list:
#     print(row.name, row.hobby_id)
### 跨表查询
# 方式一
# person_list = session.query(models.Person.name, models.Hobby.caption).join(models.Hobby, isouter=True).all()   ###left join,取特定值
# for row in person_list:
#     print(row.name, row.caption)
person_list = session.query(models.Person, models.Hobby).join(models.Hobby, isouter=True).all()   ###left join
for row in person_list:
    print(row[0].name, row[1].caption)

### 关闭session
session.close()
(3)通过relationship查询(一对多)

<1> 修改models.py

[root@Python sqlalchemy]# vim models.py           ###添加,不用再执行model.py
hobby = relationship("Hobby", backref='pers')

Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第1张图片
<2> 配置app.py(查询)

[root@Python sqlalchemy]# vim app.py
#!/usr/bin/env python
#coding:utf-8
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models

engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
    max_overflow=0,
    pool_size=5,
    pool_timeout=30,
    pool_recycle=-1,
)
Session = sessionmaker(bind=engine)
session = Session()

### 执行ORM操作
# session.add_all([
#     models.Hobby(caption='篮球'),
#     models.Hobby(caption='足球'),
# ])
# session.add_all([
#     models.Person(name='dream', hobby_id=2),
#     models.Person(name='dreamya1', hobby_id=2),
#     models.Person(name='dreamya', hobby_id=1),
#     models.Person(name='dream1', hobby_id=1),
# ])
# session.commit()
# person_list = session.query(models.Person).all()
# for row in person_list:
#     print(row.name, row.hobby_id)
##################### 查询 #########################
### 跨表查询
# 方式一
# person_list = session.query(models.Person.name, models.Hobby.caption).join(models.Hobby, isouter=True).all()   ###left join,取特定值
# for row in person_list:
#     print(row.name, row.caption)
# person_list = session.query(models.Person, models.Hobby).join(models.Hobby, isouter=True).all()   ###left join
# for row in person_list:
#     print(row[0].name, row[1].caption)
# 方式二
# 正向查询
person_list = session.query(models.Person).all()
for row in person_list:
    print(row.name, row.hobby.caption)
# 喜欢篮球的所有人,反向查询
obj = session.query(models.Hobby).filter(models.Hobby.id == 1).first()
persons = obj.pers
print(persons)
### 关闭session
session.close()

<3> 添加

[root@Python sqlalchemy]# vim app.py
#!/usr/bin/env python
#coding:utf-8
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models

engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
    max_overflow=0,
    pool_size=5,
    pool_timeout=30,
    pool_recycle=-1,
)
Session = sessionmaker(bind=engine)
session = Session()

### 执行ORM操作
# session.add_all([
#     models.Hobby(caption='篮球'),
#     models.Hobby(caption='足球'),
# ])
# session.add_all([
#     models.Person(name='dream', hobby_id=2),
#     models.Person(name='dreamya1', hobby_id=2),
#     models.Person(name='dreamya', hobby_id=1),
#     models.Person(name='dream1', hobby_id=1),
# ])
# session.commit()
# person_list = session.query(models.Person).all()
# for row in person_list:
#     print(row.name, row.hobby_id)
##################### 查询 #########################
### 跨表查询
# 方式一

# person_list = session.query(models.Person.name, models.Hobby.caption).join(models.Hobby, isouter=True).all()   ###left join,取特定值
# for row in person_list:
#     print(row.name, row.caption)
# person_list = session.query(models.Person, models.Hobby).join(models.Hobby, isouter=True).all()   ###left join
# for row in person_list:
#     print(row[0].name, row[1].caption)
# 方式二
# 正向查询
# person_list = session.query(models.Person).all()
# for row in person_list:
#     print(row.name, row.hobby.caption)
# # 喜欢篮球的所有人,反向查询
# obj = session.query(models.Hobby).filter(models.Hobby.id == 1).first()
# persons = obj.pers
# print(persons)
##################### 增加 #########################
# 反向
# hb = models.Hobby(caption='乒乓球')
# hb.pers = [models.Person(name='tony'), models.Person(name='tom')]    ###自动把乒乓球的id赋值给下面2个人
# session.add(hb)
# session.commit()
# 正向
obj = models.Person(name='dreamya2', hobby=models.Hobby(caption='羽毛球'))
session.add(obj)
session.commit()

### 关闭session
session.close()

<4> 结果
反向增加:


MariaDB [test]> select * from hobby;
+----+-----------+
| id | caption   |
+----+-----------+
|  1 | 篮球      |
|  2 | 足球      |
|  3 | 乒乓球    |
+----+-----------+

MariaDB [test]> select * from person;
+-----+----------+----------+
| nid | name     | hobby_id |
+-----+----------+----------+
|   1 | dream    |        2 |
|   2 | dreamya1 |        2 |
|   3 | dreamya  |        1 |
|   4 | dream1   |        1 |
|   5 | tony     |        3 |
|   6 | tom      |        3 |
+-----+----------+----------+

正向增加:

MariaDB [test]> select * from hobby;
+----+-----------+
| id | caption   |
+----+-----------+
|  1 | 篮球      |
|  2 | 足球      |
|  3 | 乒乓球    |
|  4 | 羽毛球    |
+----+-----------+

MariaDB [test]> select * from person;
+-----+----------+----------+
| nid | name     | hobby_id |
+-----+----------+----------+
|   1 | dream    |        2 |
|   2 | dreamya1 |        2 |
|   3 | dreamya  |        1 |
|   4 | dream1   |        1 |
|   5 | tony     |        3 |
|   6 | tom      |        3 |
|   7 | dreamya2 |        4 |
+-----+----------+----------+
(4)通过relationship查询(多对多)

<1> 配置models.py

[root@Python sqlalchemy]# vim models.py
#!/usr/bin/env python
#coding:utf-8
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import datetime
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Text, ForeignKey, DateTime, UniqueConstraint, Index
from sqlalchemy.orm import relationship

Base = declarative_base()

###################### 多对多示例 #########################
class Server2Group(Base):
    __tablename__ = 'server2group'
    id = Column(Integer, primary_key=True, autoincrement=True)
    server_id = Column(Integer, ForeignKey('server.id'))
    group_id = Column(Integer, ForeignKey('group.id'))

class Group(Base):
    __tablename__ = 'group'
    id = Column(Integer, primary_key=True)
    name = Column(String(64), unique=True, nullable=False)
    # 与生成表结构无关,仅用于查询方便
    servers = relationship('Server', secondary='server2group', backref='groups')

class Server(Base):
    __tablename__ = 'server'

    id = Column(Integer, primary_key=True, autoincrement=True)
    hostname = Column(String(64), unique=True, nullable=False)
if __name__ == '__main__':
    engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
        max_overflow=0,  # 超过连接池大小外最多创建的连接
        pool_size=5,  # 连接池大小
        pool_timeout=30,  # 池中没有线程最多等待的时间,否则报错
        pool_recycle=-1  # 多久之后对线程池中的线程进行一次连接的回收(重置)
    )
    Base.metadata.create_all(engine)

<2> 配置app.py

[root@Python sqlalchemy]# vim app.py
#!/usr/bin/env python
#coding:utf-8
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
import models

engine = create_engine(
    "mysql+pymysql://root:[email protected]:3306/test?charset=utf8",
    max_overflow=0,
    pool_size=5,
    pool_timeout=30,
    pool_recycle=-1,
)
Session = sessionmaker(bind=engine)
session = Session()

############# 添加 ############
session.add_all([
    models.Server(hostname='c1.com'),
    models.Server(hostname='c2.com'),
    models.Group(name='A组'),
    models.Group(name='B组'),
])
session.commit()

s2g = models.Server2Group(server_id=1, group_id=1)
session.add(s2g)
session.commit()

gp = models.Group(name='C组')
gp.servers = [models.Server(hostname='c3.com'),models.Server(hostname='c4.com')]
session.add(gp)
session.commit()

ser = models.Server(hostname='c6.com')
ser.groups = [models.Group(name='F组'), models.Group(name='G组')]
session.add(ser)
session.commit()

### 使用relationship正向查询
"""
v = session.query(models.Group).first()
print(v.name)
print(v.servers)
"""

### 使用relationship反向查询
"""
v = session.query(models.Server).first()
print(v.hostname)
print(v.groups)
"""
### 关闭session
session.close()
(5)关联子查询
#!/usr/bin/env python
#coding:utf-8
import time
import threading

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import create_engine
from sqlalchemy.sql import text, func
from sqlalchemy.engine.result import ResultProxy
from db import Users, Hosts, Hobby, Person, Group, Server, Server2Group

engine = create_engine("mysql+pymysql://root:[email protected]:3306/s6?charset=utf8", max_overflow=0, pool_size=5)
Session = sessionmaker(bind=engine)
session = Session()

### 关联子查询
subqry = session.query(func.count(Server.id).label("sid")).filter(Server.id == Group.id).correlate(Group).as_scalar()
result = session.query(Group.name, subqry)
"""
SELECT `group`.name AS group_name, (SELECT count(server.id) AS sid 
FROM server 
WHERE server.id = `group`.id) AS anon_1 
FROM `group`
"""

### 原生SQL
"""
# 查询
cursor = session.execute('select * from users')
result = cursor.fetchall()

# 添加
cursor = session.execute('insert into users(name) values(:value)',params={"value":'wupeiqi'})
session.commit()
print(cursor.lastrowid)
"""
session.close()

二、Flask-SQLAlchemy使用


文件和目录的管理,下面介绍蓝图Flask-SQLAlchemy共同使用的目录结构及方法

1、安装Flask-SQLAlchemy

下载链接:https://pypi.org/project/Flask-SQLAlchemy/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/9b/62/80a56f9d223f0b89cdcf7d592455375f8c9d73866f337fa85f39f45fe0c5/Flask-SQLAlchemy-2.4.0.tar.gz
[root@Python ~]# tar xf Flask-SQLAlchemy-2.4.0.tar.gz
[root@Python ~]# cd Flask-SQLAlchemy-2.4.0/
[root@Python Flask-SQLAlchemy-2.4.0]# python setup.py install

2、目录结构

[root@Python Flask]# tree Project
Project
|-- create_table.py
|-- Project
|   |-- __init__.py
|   |-- models.py
|   |-- settings.py
|   |-- static
|   |-- templates
|   `-- views
|       `-- account.py
`-- run.py

Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第2张图片

3、内容

(1)配置create_table.py
[root@Python Flask]# vim Project/create_table.py
#!/usr/bin/env python
#coding:utf-8

from Project import create_app
from Project import db
app = create_app()

with app.app_context():
    db.create_all()
(2)配置run.py
[root@Python Flask]# vim Project/run.py
#!/usr/bin/env python
#coding:utf-8

from Project import create_app
app = create_app()

if __name__ == '__main__':
    app.run(host='10.10.10.111')
(3)配置__init__.py
[root@Python Flask]# vim Project/Project/__init__.py
#!/usr/bin/env python
#coding:utf-8

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
from .models import *
from .views import account

def create_app():
    app = Flask(__name__)
    app.config.from_object('Project.settings.DevelopmentConfig')
    ### 将db注册到app中
    db.init_app(app)
    ### 注册蓝图
    app.register_blueprint(account.account)
    return app
(4)配置models.py
[root@Python Flask]# vim Project/Project/models.py
#!/usr/bin/env python
#coding:utf-8

from . import db

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)

    def __repr__(self):
        return '' % self.username
(5)配置settings.py
[root@Python Flask]# vim Project/Project/settings.py
#!/usr/bin/env python
#coding:utf-8

class BaseConfig(object):
    # SESSION_TYPE = 'redis'             ###session类型为redis
    # SESSION_KEY_PREFIX = 'session:'    ###保存到session中的值的前缀
    # SESSION_PERMANENT = True           ###如果设置为False,则关闭浏览器session就失效
    # SESSION_USE_SIGNER = False         ###是否对发送到浏览器上的session:cookie值进行加密
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:[email protected]:3306/s1?charset=utf8'
    SQLALCHEMY_POOL_SIZE = 5
    SQLALCHEMY_POOL_TIMEOUT = 30
    SQLALCHEMY_POOL_RECYCLE = -1

    ### 追踪对象的修改并且发送信号
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class ProductionConfig(BaseConfig):
    pass

class DevelopmentConfig(BaseConfig):
    pass

class TestingConfig(BaseConfig):
    pass
(6)配置account.py
[root@Python Flask]# vim Project/Project/views/account.py
#!/usr/bin/env python
#coding:utf-8

from flask import Blueprint
from .. import db
from .. import models
account = Blueprint('account', __name__)

@account.route('/login')
def login():
    """
    操作方法:
    db.session.add(models.Users(username='dream',eamil='[email protected]'))
    db.session.commit()
    db.session.close()
    """
    return 'login'

三、pipreqs


查找Python项目依赖并生成requirements.txt
安装包百度网盘链接:https://pan.baidu.com/s/1DSiwaHM4sY2mZ3vd1Iw8eQ 提取码: ik1r

1、pipreqs依赖安装

(1)certifi安装

下载地址:https://pypi.org/project/certifi/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/c5/67/5d0548226bcc34468e23a0333978f0e23d28d0b3f0c71a151aef9c3f7680/certifi-2019.6.16.tar.gz
[root@Python ~]# tar xf certifi-2019.6.16.tar.gz
[root@Python ~]# cd certifi-2019.6.16/
[root@Python certifi-2019.6.16]# python setup.py install
(2)urllib3安装

下载地址:https://pypi.org/project/urllib3/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/4c/13/2386233f7ee40aa8444b47f7463338f3cbdf00c316627558784e3f542f07/urllib3-1.25.3.tar.gz
[root@Python ~]# tar xf urllib3-1.25.3.tar.gz
[root@Python ~]# cd urllib3-1.25.3/
[root@Python urllib3-1.25.3]# python setup.py install
(3)idna安装

下载地址:https://pypi.org/project/idna/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/ad/13/eb56951b6f7950cadb579ca166e448ba77f9d24efc03edd7e55fa57d04b7/idna-2.8.tar.gz
[root@Python ~]# tar xf idna-2.8.tar.gz
[root@Python ~]# cd idna-2.8/
[root@Python idna-2.8]# python setup.py install
(4)chardet安装

下载地址:https://pypi.org/project/chardet/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/fc/bb/a5768c230f9ddb03acc9ef3f0d4a3cf93462473795d18e9535498c8f929d/chardet-3.0.4.tar.gz
[root@Python ~]# tar xf chardet-3.0.4.tar.gz
[root@Python ~]# cd chardet-3.0.4/
[root@Python chardet-3.0.4]# python setup.py install
(5)requests安装

下载地址:https://pypi.org/project/requests/#files


[root@Python ~]# wget https://files.pythonhosted.org/packages/01/62/ddcf76d1d19885e8579acb1b1df26a852b03472c0e46d2b959a714c90608/requests-2.22.0.tar.gz
[root@Python ~]# tar xf requests-2.22.0.tar.gz
[root@Python ~]# cd requests-2.22.0/
[root@Python requests-2.22.0]# python setup.py install
(6)yarg安装

https://pypi.org/project/yarg/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/d4/c8/cc640404a0981e6c14e2044fc64e43b4c1ddf69e7dddc8f2a02638ba5ae8/yarg-0.1.9.tar.gz
[root@Python ~]# tar xf yarg-0.1.9.tar.gz
[root@Python ~]# cd yarg-0.1.9/
[root@Python yarg-0.1.9]# python setup.py install
(7)docopt安装

下载地址:https://pypi.org/project/docopt/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/a2/55/8f8cab2afd404cf578136ef2cc5dfb50baa1761b68c9da1fb1e4eed343c9/docopt-0.6.2.tar.gz
[root@Python ~]# tar xf docopt-0.6.2.tar.gz
[root@Python ~]# cd docopt-0.6.2/
[root@Python docopt-0.6.2]# python setup.py install

2、pipreqs安装

下载地址:https://pypi.org/project/pipreqs/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/67/63/84409df1acd879d239e53599de2b3df45013e6cf46406fd94e86822635f3/pipreqs-0.4.9.tar.gz
[root@Python ~]# tar xf pipreqs-0.4.9.tar.gz
[root@Python ~]# cd pipreqs-0.4.9/
[root@Python pipreqs-0.4.9]# python setup.py install

3、windows操作Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第3张图片

四、Flask-Script


1、安装Flask-Script

用于实现类似Django python manage.py runserver…
下载链接:https://pypi.org/project/Flask-Script/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/00/a4/cd587b2b19f043b65bf33ceda2f6e4e6cdbd0ce18d01a52b9559781b1da6/Flask-Script-2.0.6.tar.gz
[root@Python ~]# tar xf Flask-Script-2.0.6.tar.gz
[root@Python ~]# cd Flask-Script-2.0.6/
[root@Python Flask-Script-2.0.6]# python setup.py install

2、Flask-Script使用

(1)配置run.py
[root@Python Project]# vim run.py
#!/usr/bin/env python
#coding:utf-8
from Project import create_app
from flask_script import Manager

app = create_app()
manager = Manager(app)
if __name__ == '__main__':
    manager.run()
(2)在win中直接运行

直接运行让我们输入命令

Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第4张图片

(3)运行方法

运行程序:python <文件名> runserver

[root@Python Project]# ls
create_table.py  Project  run.py
[root@Python Project]# python run.py runserver             ###运行方法
 * Serving Flask app "Project" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

[root@Python Project]# python run.py runserver --help      ###查看帮助
usage: run.py runserver [-?] [-h HOST] [-p PORT] [--threaded]
                        [--processes PROCESSES] [--passthrough-errors] [-d]
                        [-D] [-r] [-R] [--ssl-crt SSL_CRT] [--ssl-key SSL_KEY]

Runs the Flask development server i.e. app.run()

optional arguments:
  -?, --help            show this help message and exit
  -h HOST, --host HOST
  -p PORT, --port PORT
  --threaded
  --processes PROCESSES
  --passthrough-errors
  -d, --debug           enable the Werkzeug debugger (DO NOT use in production
                        code)
  -D, --no-debug        disable the Werkzeug debugger
  -r, --reload          monitor Python files for changes (not 100% safe for
                        production use)
  -R, --no-reload       do not monitor Python files for changes
  --ssl-crt SSL_CRT     Path to ssl certificate
  --ssl-key SSL_KEY     Path to ssl key
(4)自定义命令

<1> 配置run.py

[root@Python Project]# vim run.py
#!/usr/bin/env python
#coding:utf-8
from Project import create_app
from flask_script import Manager

app = create_app()
manager = Manager(app)
@manager.command
def custom(arg):
    """
    自定义命令
    python run.py custom 123
    :param arg:
    :return:
    """
    print(arg)

@manager.option('-n', '--name', dest='name')
@manager.option('-u', '--url', dest='url')
def cmd(name, url):
    """
    自定义命令
    执行:python run.py cmd -n dream -u http://www.dreamya.top
    :param name:
    :param url:
    :return:
    """
    print(name, url)

if __name__ == '__main__':
    manager.run()

<2> 查看结果
在这里插入图片描述
五、Flask-Migrate


用于实现类似Django的数据库迁移
百度网盘下载链接:https://pan.baidu.com/s/14pK8NTdBt8KFCzgPrzZrxA 提取码: 2g5j

1、依赖安装

(1)安装setuptools_scm

下载链接:https://pypi.org/project/setuptools-scm/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/83/44/53cad68ce686585d12222e6769682c4bdb9686808d2739671f9175e2938b/setuptools_scm-3.3.3.tar.gz
[root@Python ~]# tar xf setuptools_scm-3.3.3.tar.gz
[root@Python ~]# cd setuptools_scm-3.3.3/
[root@Python setuptools_scm-3.3.3]# python setup.py install
(2)安装six

下载链接:https://pypi.org/project/six/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/dd/bf/4138e7bfb757de47d1f4b6994648ec67a51efe58fa907c1e11e350cddfca/six-1.12.0.tar.gz
[root@Python ~]# tar xf six-1.12.0.tar.gz
[root@Python ~]# cd six-1.12.0/
[root@Python six-1.12.0]# python setup.py install
(3)安装python-dateutil

下载地址:https://pypi.org/project/python-dateutil/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/ad/99/5b2e99737edeb28c71bcbec5b5dda19d0d9ef3ca3e92e3e925e7c0bb364c/python-dateutil-2.8.0.tar.gz
[root@Python ~]# tar xf python-dateutil-2.8.0.tar.gz
[root@Python ~]# cd python-dateutil-2.8.0/
[root@Python python-dateutil-2.8.0]# python setup.py install
(4)安装python-editor

下载链接:https://pypi.org/project/python-editor/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/0a/85/78f4a216d28343a67b7397c99825cff336330893f00601443f7c7b2f2234/python-editor-1.0.4.tar.gz
[root@Python ~]# tar xf python-editor-1.0.4.tar.gz
[root@Python ~]# cd python-editor-1.0.4/
[root@Python python-editor-1.0.4]# python setup.py install
(5)安装Mako

下载链接:https://pypi.org/project/Mako/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/b0/3c/8dcd6883d009f7cae0f3157fb53e9afb05a0d3d33b3db1268ec2e6f4a56b/Mako-1.1.0.tar.gz
[root@Python ~]# tar xf Mako-1.1.0.tar.gz
[root@Python ~]# cd Mako-1.1.0/
[root@Python Mako-1.1.0]# python setup.py install
(6)安装alembic

下载地址:https://pypi.org/project/alembic/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/7b/8b/0c98c378d93165d9809193f274c3c6e2151120d955b752419c7d43e4d857/alembic-1.0.11.tar.gz
[root@Python ~]# tar xf alembic-1.0.11.tar.gz
[root@Python ~]# cd alembic-1.0.11/
[root@Python alembic-1.0.11]# python setup.py install

2、安装Flask-Migrate

下载地址:https://pypi.org/project/Flask-Migrate/#files

[root@Python ~]# wget https://files.pythonhosted.org/packages/c5/36/906fd843dcd7996bca42ed5bf8e3d70bac64fd81fc492e099aa739c961db/Flask-Migrate-2.5.2.tar.gz
[root@Python ~]# tar xf Flask-Migrate-2.5.2.tar.gz
[root@Python ~]# cd Flask-Migrate-2.5.2/
[root@Python Flask-Migrate-2.5.2]# python setup.py install

3、Flask-Migrate使用

(1)配置run.py
[root@Python Project]# vim run.py
#!/usr/bin/env python
#coding:utf-8
from Project import create_app, db
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
app = create_app()
manager = Manager(app)
migrate = Migrate(app, db)
"""
数据库命令
    python run.py db init
    python run.py db migrate
    python run.py db upgrade
"""
manager.add_command('db', MigrateCommand)

@manager.command
def custom(arg):
    """
    自定义命令
    python run.py custom 123
    :param arg:
    :return:
    """
    print(arg)

@manager.option('-n', '--name', dest='name')
@manager.option('-u', '--url', dest='url')
def cmd(name, url):
    """
    自定义命令
    执行:python run.py cmd -n dream -u http://www.dreamya.top
    :param name:
    :param url:
    :return:
    """
    print(name, url)

if __name__ == '__main__':
    manager.run()

Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第5张图片

(2)结果

upgrade我们可以把models中的Users表的email注释掉,在执行就可以删除此行,并且之前的数据不会删除

Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第6张图片

生成配置文件:
Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第7张图片
提交到数据库:
Flask入门(四)之SQLAlchemy、Flask-SQLAlchemy、pipreqs、Flask-Script、Flask-Migrate_第8张图片

你可能感兴趣的:(Flask)