1. 程式人生 > >python3-開發進階Flask的基礎(5)

python3-開發進階Flask的基礎(5)

下載安裝 ini extra www als 協同開發 通配 化學 first

內容概要:

  1. SQLAlchemy
  2. flsak-sqlalchemy
  3. flask-script
  4. flask-migrate
  5. Flask的目錄結構

一、SQLAlchemy

1、概述

SQLAlchemy是一個ORM的框架,ORM就是關系對象映射,具體可以參照Django中的ORM。

作用:幫助我們使用類和對象快速實現數據庫操作

數據庫:

  -原生:MYSQLdb pymysql

  區別就是 MYSQLdb 不支持python3 pymysql 都支持

ORM框架

  SQLAlchemy

2、SQLAlchemy用法  

1、安裝

pip3 install sqlalchemy

2、配置

技術分享圖片
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy import Integer,String,Text,Date,DateTime
from sqlalchemy import create_engine


Base = declarative_base()

class Users(Base):
    __tablename__ = users
id = Column(Integer, primary_key=True) name = Column(String(32), index=True, nullable=False) def create_all(): engine = create_engine( "mysql+pymysql://root:[email protected]:3306/duoduo123?charset=utf8", max_overflow=0, # 超過連接池大小外最多創建的連接 pool_size=5, # 連接池大小
pool_timeout=30, # 池中沒有線程最多等待的時間,否則報錯 pool_recycle=-1 # 多久之後對線程池中的線程進行一次連接的回收(重置) ) Base.metadata.create_all(engine) def drop_all(): engine = create_engine( "mysql+pymysql://root:[email protected]:3306/duoduo123?charset=utf8", max_overflow=0, # 超過連接池大小外最多創建的連接 pool_size=5, # 連接池大小 pool_timeout=30, # 池中沒有線程最多等待的時間,否則報錯 pool_recycle=-1 # 多久之後對線程池中的線程進行一次連接的回收(重置) ) Base.metadata.drop_all(engine) if __name__ == __main__: create_all()
配置

3、增刪改查的演示

技術分享圖片
from duoduo.test import Users
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine


engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/duoduo123?charset=utf8",
        max_overflow=0,  # 超過連接池大小外最多創建的連接
        pool_size=5,  # 連接池大小
        pool_timeout=30,  # 池中沒有線程最多等待的時間,否則報錯
        pool_recycle=-1  # 多久之後對線程池中的線程進行一次連接的回收(重置)
    )



SessionFactory = sessionmaker(bind=engine)

#根據Users類對user表進行增刪改查
session=SessionFactory()
#增加
#單個
# obj=Users(name=‘many qian‘)
# session.add(obj)
# session.commit()
#多個
# session.add_all([
#         Users(name=‘大娃‘),
#         Users(name=‘二娃‘)
# ])
# session.commit()

#查  所有
# tes=session.query(Users).all()
# print(tes) #拿到的對象
# for row in tes:
#         print(row.id,row.name)

# tes=session.query(Users).filter(Users.id==3) #> < >= <=
#
# for row in tes:
#     print(row.id,row.name)

#
# tes=session.query(Users).filter(Users.id<=3).first()#> < >= <=
#
# print(tes.id,tes.name)

#刪除
# tes=session.query(Users).filter(Users.id==3).delete() #> < >= <=
# session.commit()

#
# session.query(Users).filter(Users.id ==4).update({Users.name:‘三娃‘})
# session.query(Users).filter(Users.id ==4).update({‘name‘:‘四娃‘})
# session.query(Users).filter(Users.id ==4).update({‘name‘:Users.name+‘NICE‘},synchronize_session=False)
# session.commit()
#
#
# session.close()
增刪改查

4、單表常用操作

技術分享圖片
# ############################## 其他常用 ###############################
# 1. 指定列
# select id,name as cname from users;
# result = session.query(Users.id,Users.name.label(‘cname‘)).all()
# for item in result:
#         print(item[0],item.id,item.cname)
# 2. 默認條件and
# session.query(Users).filter(Users.id > 1, Users.name == ‘duoduo‘).all()
# 3. between
# session.query(Users).filter(Users.id.between(1, 3), Users.name == ‘duoduo‘).all()
# 4. in
# session.query(Users).filter(Users.id.in_([1,3,4])).all()
# session.query(Users).filter(~Users.id.in_([1,3,4])).all()
# 5. 子查詢
# session.query(Users).filter(Users.id.in_(session.query(Users.id).filter(Users.name==‘duoduo‘))).all()
# 6. and 和 or
# from sqlalchemy import and_, or_
# session.query(Users).filter(Users.id > 3, Users.name == ‘duoduo‘).all()
# session.query(Users).filter(and_(Users.id > 3, Users.name == ‘duoduo‘)).all()
# session.query(Users).filter(or_(Users.id < 2, Users.name == ‘duoduo‘)).all()
# session.query(Users).filter(
#     or_(
#         Users.id < 2,
#         and_(Users.name == ‘duoduo‘, Users.id > 3),
#         Users.extra != ""
#     )).all()

# 7. filter_by
# session.query(Users).filter_by(name=‘duoduo‘).all()

# 8. 通配符
# ret = session.query(Users).filter(Users.name.like(‘d%‘)).all()   #%任何的東西
# ret = session.query(Users).filter(~Users.name.like(‘d_‘)).all()   #_ 只有一個字符

# 9. 切片
# result = session.query(Users)[1:2]

# 10.排序
# ret = session.query(Users).order_by(Users.name.desc()).all()
# ret = session.query(Users).order_by(Users.name.desc(), Users.id.asc()).all()  #desc從大到小  asc從小到大排

# 11. group by
from sqlalchemy.sql import func

# ret = session.query(
#         Users.depart_id,
#         func.count(Users.id),
# ).group_by(Users.depart_id).all()
# for item in ret:
#         print(item)
#
# from sqlalchemy.sql import func
#進行二次篩選,只能用having
# ret = session.query(
#         Users.depart_id,
#         func.count(Users.id),
# ).group_by(Users.depart_id).having(func.count(Users.id) >= 2).all()
# for item in ret:
#         print(item)

# 12.union 去重 和 union all 上下拼接不去重
"""
select id,name from users
UNION
select id,name from users;
"""
# q1 = session.query(Users.name).filter(Users.id > 2)
# q2 = session.query(Users.name).filter(Users.id > 2)
# ret = q1.union(q2).all()
#
# q1 = session.query(Users.name).filter(Users.id > 2)
# q2 = session.query(Users.name).filter(Users.id > 2)
# ret = q1.union_all(q2).all()


session.close()
單表常用操作

5、連表常用操作

在上面的配置裏,重新搞兩給表

from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
#按照上面配置的代碼加上這些東西,配置的表刪除 
class Depart(Base):
    __tablename__ = depart
    id = Column(Integer, primary_key=True)
    title = Column(String(32), index=True, nullable=False)

class Users(Base):
    __tablename__ = users

    id = Column(Integer, primary_key=True)
    name = Column(String(32), index=True, nullable=False)
    depart_id = Column(Integer,ForeignKey("depart.id"))
    #跟表結構無關
    dp = relationship("Depart", backref=pers)

下面是實例演示:之前自己添加一點數據:

技術分享圖片
#django的manytomany  在flask中兩個ForeignKey完成
from duoduo.test import Users,Depart,Student,Course,Student2Course
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine


engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/duoduo123?charset=utf8",
        max_overflow=0,  # 超過連接池大小外最多創建的連接
        pool_size=5,  # 連接池大小
        pool_timeout=30,  # 池中沒有線程最多等待的時間,否則報錯
        pool_recycle=-1  # 多久之後對線程池中的線程進行一次連接的回收(重置)
    )



SessionFactory = sessionmaker(bind=engine)

#根據Users類對user表進行增刪改查
session=SessionFactory()

# #1、查詢所有用戶
# # ret =session.query(Users).all()
# #
# # for i in ret:
# #     print(i.id,i.name,i.depart_id)

#2、查詢所有用戶,所屬部門名稱
# ret=session.query(Users.id,Users.name,Depart.title).join(Depart,User.depart_id==Depart.id).all()
#  #這裏有默認ForeignKey ,User.depart_id==Depart.id 可以不加也行
# for i in ret:
#     print(i.id ,i.name,i.title)

#SELECT users.id AS users_id, users.name AS users_name, depart.title AS depart_title
#FROM users INNER JOIN depart ON depart.id = users.depart_id
# q=session.query(Users.id,Users.name,Depart.title).join(Depart)
# print(q)

#3、relation字段:查詢所有用戶+所有部門名稱
# ret=session.query(Users).all()
# for row in ret:
#     print(row.id,row.name,row.depart_id,row.dp.title)

#4、relation字段:查詢銷售部所有人員
# obj=session.query(Depart).filter(Depart.title ==‘大娃‘).first()
# # for i in obj.pers:
# #     print(i.id,i.name,obj.title)

#5、創建一個名稱叫:IT部門,再在該部門中添加一個員工叫:多多
#方式一:
# d1=Depart(title=‘IT‘)
# session.add(d1)
# session.commit()
#
# u1=Users(name=‘duoduo‘,depart_id=d1.id)
# session.add(u1)
# session.commit()
#方式二:
# u1=Users(name=‘多多1‘,dp=Depart(title=‘IT‘))
# session.add(u1)
# session.commit()


#6、創建一個部門叫王者榮耀,這個部門添加多個員工:亞瑟,後裔,貂蟬

# d1=Depart(title=‘王者榮耀‘)
# d1.pers=[Users(name=‘亞瑟‘),Users(name=‘後裔‘),Users(name=‘貂蟬‘)]
#
# session.add(d1)
# session.commit()


#1、錄入數據
# session.add_all([
#     Student(name=‘大娃‘),
#     Student(name=‘二娃‘),
#     Course(title=‘物理‘),
#     Course(title=‘化學‘),
#
# ])
# session.add_all([
#     Student2Course(student_id=2,course_id=1),
#     # Student2Course(student_id=1,course_id=2)
# ]
# )

#2、查每個人選了課程的名稱,三張表進行關聯
# ret=session.query(Student2Course.id,Student.name,Course.title).join(Student,Student2Course.student_id==Student.id,isouter=True).join(Course,Student2Course.course_id==Course.id,isouter=True).order_by(Student2Course.id.asc())
# for i in ret:
#     print(i)

#3、‘大娃‘所選的所有課

# ret=session.query(Student2Course.id,Student.name,Course.title).join(Student,Student2Course.student_id==Student.id,isouter=True).join(Course,Student2Course.course_id==Course.id,isouter=True).filter(Student.name==‘大娃‘).order_by(Student2Course.id.asc())
#
# for i in ret:
#     print(i)

# obj=session.query(Student).filter(Student.name==‘大娃‘).first()
# for item in obj.course_list:
#     print(item.title)
#4選了‘化學‘課程的所有人的名字
# obj=session.query(Course).filter(Course.title==‘化學‘).first()
# for item in obj.student_list:
#     print(item.name)


#創建一個課程,創建2個學,兩個學生選新創建的課程
# obj=Course(title=‘體育‘)
# obj.student_list=[Student(name=‘五娃‘),Student(name=‘六娃‘)]
#
# session.add(obj)
# session.commit()








# session.close()
ForeignKey 技術分享圖片
class Student(Base):
    __tablename__ = student
    id = Column(Integer, primary_key=True)
    name = Column(String(32), index=True, nullable=False)

    course_list = relationship(Course, secondary=student2course, backref=student_list)

class Course(Base):
    __tablename__ = course
    id = Column(Integer, primary_key=True)
    title = Column(String(32), index=True, nullable=False)

class Student2Course(Base):
    __tablename__ = student2course
    id = Column(Integer, primary_key=True, autoincrement=True)
    student_id = Column(Integer, ForeignKey(student.id))
    course_id = Column(Integer, ForeignKey(course.id))

    __table_args__ = (
        UniqueConstraint(student_id, course_id, name=uix_stu_cou), # 聯合唯一索引
        # Index(‘ix_id_name‘, ‘name‘, ‘extra‘),        # 聯合索引
    )
後面新建的三個表

連接的方式:

from duoduo.test import Users,Depart,Student,Course,Student2Course
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine


engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/duoduo123?charset=utf8",
        max_overflow=0,  # 超過連接池大小外最多創建的連接
        pool_size=5,  # 連接池大小
        pool_timeout=30,  # 池中沒有線程最多等待的時間,否則報錯
        pool_recycle=-1  # 多久之後對線程池中的線程進行一次連接的回收(重置)
    )



SessionFactory = sessionmaker(bind=engine)


#連接
#第一種方式
# #並發
# def task():
#     #去連接池獲取一個連接
#     session=SessionFactory()
#     ret=session.query(Student).all()
#     print(ret)
#     #將連接交還給連接池
#     session.close()
#
#
# from threading import Thread
#
# for i in range(20):
#     t=Thread(target=task)
#     t.start()
#

#第二種方式

from sqlalchemy.orm import scoped_session
session=scoped_session(SessionFactory)


def task():
    ret=session.query(Student).all()
    print(ret)
    session.remove()  #連接斷開


from threading import Thread
for i in range(20):
    t=Thread(target=task)
    t.start()

執行原生SQ:

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session
from models import Student,Course,Student2Course

engine = create_engine(
        "mysql+pymysql://root:[email protected]:3306/duoduo123?charset=utf8",
        max_overflow=0,  # 超過連接池大小外最多創建的連接
        pool_size=5,  # 連接池大小
        pool_timeout=30,  # 池中沒有線程最多等待的時間,否則報錯
        pool_recycle=-1  # 多久之後對線程池中的線程進行一次連接的回收(重置)
    )
SessionFactory = sessionmaker(bind=engine)
session = scoped_session(SessionFactory)


def task():
    """"""
    # 方式一:
    """
    # 查詢
    # cursor = session.execute(‘select * from users‘)
    # result = cursor.fetchall()

    # 添加
    cursor = session.execute(‘INSERT INTO users(name) VALUES(:value)‘, params={"value": ‘duoduo‘})
    session.commit()
    print(cursor.lastrowid)
    """
    # 方式二:
    """
    # conn = engine.raw_connection()
    # cursor = conn.cursor()
    # cursor.execute(
    #     "select * from t1"
    # )
    # result = cursor.fetchall()
    # cursor.close()
    # conn.close()
    """

    # 將連接交還給連接池
    session.remove()


from threading import Thread

for i in range(20):
    t = Thread(target=task)
    t.start()

二、Flask的第三方組件

1、flask-sqlalchemy

a、先下載安裝

pip3 install flask-sqlalchemy

b、項目下的__init__.py導入

#第一步  :導入並實例化SQLALchemy
from flask_sqlalchemy import SQLAlchemy
db=SQLAlchemy()
#一定要在藍圖導入的上面,是全局變量
#也要導入表的models.py的所有表

c、初始化

db.init_app(app)  
#在註冊藍圖的地方的下面

d、在配置文件中寫入配置

# ##### SQLALchemy配置文件 #####
    SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:[email protected]:3306/duoduo?charset=utf8"
    SQLALCHEMY_POOL_SIZE = 10
    SQLALCHEMY_MAX_OVERFLOW = 5

e、創建models.py中的類(對應數據庫中的表)

from sqlalchemy import Column
from sqlalchemy import Integer,String,Text,Date,DateTime
from (項目目錄) import db

class Users(db.Model):  #繼承的db.Model
    __tablename__ = users

    id = Column(Integer, primary_key=True)
    name = Column(String(32), index=True, nullable=False)
    # depart_id = Column(Integer)

f、生成表(使用app上下文)

from (項目目錄) 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中獲取配置

補充一個知識點:

class  Foo(object):
    def __enter__(self):
        print(進入)

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(出來)
obj =Foo()
with obj:  #with Foo()
    print(多多)

#結果 
#進入
#多多
#出來

g、基於ORM對數據庫進行操作

from flask import Blueprint
from (項目目錄) import db
from (項目目錄) import models
us = Blueprint(us,__name__)

@us.route(/index)
def index():
    # 使用SQLAlchemy在數據庫中插入一條數據
    # db.session.add(models.Users(name=‘多多‘,depart_id=1))     #插入數據
    # db.session.commit()
    # db.session.remove()
    result = db.session.query(models.Users).all()
    print(result)
    db.session.remove()
    return Index

這裏面db.session.add的源碼:

技術分享圖片

技術分享圖片

2、 flask-script

下載安裝

pip3 install flask-script

功能:

  a、增加runsever

from (項目目錄) import create_app
from flask_script import Manager

app = create_app()
manager = Manager(app)

if __name__ == __main__:
    # app.run()
    manager.run()

  b、位置傳參

from (項目目錄) import create_app
from flask_script import Manager

app = create_app()
manager = Manager(app)

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

if __name__ == __main__:
    # app.run()
    manager.run()

  c、關鍵字傳參  

from flask_script import Manager
from (項目目錄) import create_app

app = create_app()
manager = Manager(app)

@manager.option(-n, --name, dest=name)
@manager.option(-u, --url, dest=url)
def cmd(name, url):
    """
    自定義命令
    執行: python manage.py  cmd -n qianduoduo -u http://www.baidu.com
    :param name:
    :param url:
    :return:
    """
    print(name, url)

if __name__ == __main__:
    # app.run()
    manager.run()

3、flask-migrate

安裝

pip3 install flask-migrate

配置是依賴 flask-script

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from (項目目錄) import create_app
from (項目目錄) import db

app = create_app()
manager = Manager(app)
Migrate(app, db)
"""
# 數據庫遷移命名
    python manage.py db init   #只執行一次
    python manage.py db migrate # makemirations
    python manage.py db upgrade # migrate
"""
manager.add_command(db, MigrateCommand)

if __name__ == __main__:
    # app.run()
    manager.run()

補充工具:(協同開發的保證開發的環境一致性)

1、pipreqs

找到項目使用的所有組件的版本

pip3 install  pipreqs

在項目中的命令行

pipreqs ./ --encoding=utf-8

在項目中找了文件requirements.txt

如何裝那些模塊?

pip install 的時候可以指定一個文件,他會自己讀每一行,然後安裝

pycharm 打開文件的時候也會提示下載

2、虛擬環境 (開發環境版本不能共存的)

安裝

pip3 install virtualenv

創建虛擬環境

#找一個存放虛擬環境的文件夾
virtualenv env1 --no-site-packages  創建環境

activate  #激活環境

deactivate # 退出環境


#也可以用pycharm鼠標點點就好了,最新的版本就有虛擬環境goon功能
#當我們需要特定的環境,可以在電腦上有多高開發環境

python3-開發進階Flask的基礎(5)