Flask 入門 (10): Flask は SQLAlchemy を使用します

11.SQL錬金術

11.1 はじめに

SQLAlchemy は、アプリケーション開発者に SQL のパワーと柔軟性を提供する Python SQL ツールキットおよびオブジェクト リレーショナル マッパーです。これは、効率的かつ高パフォーマンスのデータベース アクセスのために設計されたエンタープライズ レベルの永続パターンの完全なセットを提供し、シンプルな Python ドメイン言語に適応されています。
SQLAlchemy は、Python 世界の ORM (オブジェクト リレーショナル マッパー) フレームワークであり、SQLAlchemy ORM と SQLAlchemy Core という 2 つの主要コンポーネントがあります。

画像

11.2 インストール

pip install SQLAlchemy

11.3 基本的な使い方

テーブルを作成する

このクラスは宣言型を使用し、データベース テーブルの名前を定義するために少なくとも 1 つの __tablename__ 属性を必要とし、少なくとも 1 つの列が主キーである必要があります。

# SQLAlchemy练习
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, UniqueConstraint, Index
from sqlalchemy.ext.declarative import declarative_base
# declarative_base类维持了一个从类到表的关系,通常一个应用使用一个base实例,所有实体类都应该继承此类对象

Base = declarative_base()

# 类使用声明式至少需要一个__tablename__属性定义数据库表名字,并至少一Column是主键
# 创建单表
class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(32))
    extra = Column(String(16))


def init_db():
    # 数据库链接引擎
    engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)
    # 创建表
    Base.metadata.create_all(engine)

def drop_db():
    engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)
    # 删除表
    Base.metadata.drop_all(engine)

if __name__ == "__main__":
    init_db()
    # drop_db()

データを挿入する

# SQLAlchemy练习
import models
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 数据库链接引擎
engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)

se = sessionmaker(bind=engine)
session = se()

u1 = models.User(name='a1', extra='aa')
u2 = models.User(name='a2', extra='bb')

session.add(u1)
session.add(u2)


session.commit()
# session.rollback() # 回滚

session.rollback() はロールバックを意味します

11.4 接続

SQLAlchemy は、エンジンのソースを、エンジン オプションを設定するオプションの文字列パラメーターを備えた URI として表します。URI の形式は次のとおりです。

dialect+driver://username:password@host:port/database

この文字列の多くの部分はオプションです。ドライブが指定されていない場合は、デフォルトが選択されます (この場合は + を含めないでください)。

ポストグレ:

postgresql://scott:tiger@localhost/mydatabase

MySQL:

mysql://scott:tiger@localhost/mydatabaseOracle:

オラクル:

//scott:tiger@127.0.0.1:1521/sidname

SQLite (先頭の 4 つのスラッシュに注意してください):

sqlite:absolute/path/to/foo.db

11.5 データ型

ここに画像の説明を書きます

SQLAlchemy 列オプション:

画像

11.6 ネイティブ SQL の実行

from sqlalchemy import create_engine

engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)

# 执行SQL
cur = engine.execute(
    "select * from users"
)

# 获取第一行数据
re1 = cur.fetchone()
# 获取第n行数据
# re2 = cur.fetchmany(2)
# 获取所有数据
re3 = cur.fetchall()

print(re3)
# 注意:当执行fetchone()后,数据已经被去除一条了,即使fetchall(),取出的数据也是从第二条数据开始的

Engine.execute はデフォルトでデータベース接続プールを使用しますが、DBUtils + pymysql を接続プールとして使用することもできます

11.7 データの挿入

後続の追加、削除、変更、およびクエリのために次のテーブルを作成します。

モデル2.py

# sqlalchemy创建多个关联表
from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, String, UniqueConstraint, Index, DateTime, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
import datetime


Base = declarative_base()


class Classes(Base):
    __tablename__ = 'classes'
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(32), nullable=False, unique=True)


class Student(Base):
    __tablename__ = 'student'
    id = Column(Integer, primary_key=True, autoincrement=True)
    username = Column(String(32), nullable=False, unique=True)
    password = Column(String(32), nullable=False)
    ctime = Column(DateTime, default=datetime.datetime.now)  # 注意now后不要加()

    # 外键:对应的班级
    class_id = Column(Integer, ForeignKey('classes.id'))


class Hobby(Base):
    __tablename__ = 'hobby'
    id = Column(Integer, primary_key=True, autoincrement=True)
    caption = Column(String(32), default='篮球')

# 建立多对多的关系
class Student2Hobby(Base):
    __tablename__ = 'student2hobby'
    id = Column(Integer, primary_key=True, autoincrement=True)
    student_id = Column(Integer, ForeignKey('student.id'))
    hobby_id = Column(Integer, ForeignKey('hobby.id'))

    # 增加联合唯一索引
    __table_args__ = (
        UniqueConstraint('student_id', 'hobby_id', name='uni_student_id_hobby_id'),
    )


def init_db():
    # 数据库链接引擎
    engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)
    # 创建表
    Base.metadata.create_all(engine)

def drop_db():
    engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)
    # 删除表
    Base.metadata.drop_all(engine)

if __name__ == "__main__":
    init_db()
    # drop_db()

上記でテーブルが作成された後、挿入操作が開始されます。

# sqlalchemy的增删改查

import models2
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 数据库链接引擎
engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)

se = sessionmaker(bind=engine)
session = se()

# 单条增加
# c1 = models2.Classes(name='python入门')
# session.add(c1)
# session.commit()
# session.close()


# 多条增加
# c2 = [
#     models2.Classes(name='python进阶'),
#     models2.Classes(name='python高级'),
#     models2.Classes(name='python web')
# ]
# session.add_all(c2)
# session.commit()
# session.close()

11.8 削除および変更操作

# sqlalchemy的增删改查

import models2
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 数据库链接引擎
engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)

se = sessionmaker(bind=engine)
session = se()



# 删除
# session.query(models2.Classes).filter(models2.Classes.id > 2).delete()
# session.commit()


# 修改
# session.query(models2.Classes).filter(models2.Classes.id > 2).update({"name" : "099"})
session.query(models2.Classes).filter(models2.Classes.id > 2).update({
    
    models2.Classes.name: models2.Classes.name + "099"}, synchronize_session=False)
synchronize_session = False  # 对字段执行字符串操作
# session.query(models2.Classes).filter(models2.Classes.id > 2).update({"num": models2.Classes.num + 1}, synchronize_session="evaluate")
# synchronize_session = 'evaluate'  # 对字段执行数值型操作
session.commit()

11.9 クエリ

参考: Flask-SQLAlchemy - Wu Peiqi - ブログパーク (cnblogs.com)

1. 次のメソッドはすべて新しいクエリを返すため、エグゼキュータとともに使用する必要があります。

filter(): フィルタリング、より強力な複数テーブル関連付けクエリ。
filter_by(): フィルタリング。通常、単一テーブル クエリのフィルタリング シナリオで使用されます。

order_by(): 並べ替え。デフォルトは昇順ですが、降順では package: from sqlalchemy import * をインポートする必要があります。次にdescメソッドを導入します。例: order_by(desc("email")) メールボックスの文字の降順に並べ替えます。

group_by(): グループ化。

2. 以下は一般的に使用されるアクチュエータの一部です。上記のフィルタと組み合わせて使用​​します。

get(): ID がいくつかに等しい関数を取得します。

例: id=1 のオブジェクトをクエリします。

get(1) で覚えておいてください。括弧内に「id=」はありません。id の値を直接渡しても問題ありません。この関数の機能は、主キーがいくつかに等しいオブジェクトをクエリすることであるためです。

all(): すべてのデータをクエリします。

first(): 最初のデータをクエリします。

count(): クエリ結果の数を返します。

paginate(): ページング クエリ。ページネーション オブジェクトを返します。

paginate (パラメータ 1, パラメータ 2, パラメータ 3) => パラメータ 1: 現在のページ; パラメータ 2: 各ページに表示されるレコードの数; パラメータ 3: エラーを返すかどうか。

返されるページング オブジェクトには 3 つのプロパティがあります: items: クエリの結果を取得する、pages: 合計ページ数を取得する、page: 現在のページを取得する。

3. 一般的に使用される論理記号:

使用するにはパッケージをインポートする必要があります: from sqlalchemy import *

not_、and_、or_、および上記の並べ替えの説明。

一般的に使用される組み込みのものは次のとおりです。 in_: 特定のフィールドがどの範囲にあるかを示します。

4. 他の関係に対するいくつかのデータベース クエリ:

openswith(): で終わるもの。

startswith(): 何から始めるか。

contains(): が含まれています

# sqlalchemy的增删改查

import models2
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql import text


# 数据库链接引擎
engine = create_engine("mysql+pymysql://root:[email protected]:3306/flask01?charset=utf8", max_overflow=5)

se = sessionmaker(bind=engine)
session = se()


# 查询

r1 = session.query(models2.Classes).all()  # 返回models2.Classes对象

# label相当于sql里的as,取别名,后面结果集使用也是使用别名
r2 = session.query(models2.Classes.name.label('xx'), models2.Classes.name).all()

# 查询课程名字为python入门的课程
r3 = session.query(models2.Classes).filter(models2.Classes.name == "python入门").all()
# 也可使用filter_by,注意filter_by的传参和filter不一样
r4 = session.query(models2.Classes).filter_by(name='python入门').all()

# 查询课程名字为python入门的课程的第一个
r5 = session.query(models2.Classes).filter_by(name='python入门').first()

# 查询id<2且课程名字为python入门的课程
r6 = session.query(models2.Classes).filter(text("id<:value and name=:name")).params(value=2, name='python入门').order_by(models2.Classes.id).all()

# from_statement相当于子查询
r7 = session.query(models2.Classes).from_statement(text("SELECT * FROM Classes where name=:name")).params(name='python入门').all()

print(r7)
session.close()
# 注意:除了r2,其他结果都为models2.Classes对象
# 条件
ret = session.query(Users).filter_by(name='alex').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()

参考:
https://blog.csdn.net/u011146423/article/details/87605812

Python開発 [パート 19]: Python 操作 MySQL - Wu Peiqi - Blog Garden (cnblogs.com)

SQLAlchemy研究ノート_JP.Zhang-CSDN ブログ

おすすめ

転載: blog.csdn.net/qq_43745578/article/details/129188691