找回密码
 注册
查看: 40|回复: 1

flask sqlalchemy 操作数据相关代码和实现方法

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2024-7-28 17:00:09 | 显示全部楼层 |阅读模式
1.介绍' P7 G5 U7 s2 e# ~
flask用于orm操作表,一般使用flask- sqlalchemy 操作简单
+ A2 X" J1 Y4 j+ a2 W8 Y1 v一般使用flask-sqlalchemy 2.5.10 e3 ]8 F* {8 t1 F  x
https://flask-sqlalchemy.palletsprojects.com/en/2.x/
6 b8 a& G8 R3 t( t9 d& V1 Q' w" B% n0 g9 x3 G5 ]

- y4 c, ?) ]# @3 a; d7 @; E9 e+ b' ?4 u' `
2.安装
6 i5 g2 B8 `' hpip instal flask-sqlalchemy==2.5.1/ f% R0 O& g8 F% D- w, `* U% M
pip install Flask-Migrate==2.6.0  # 迁移数据库使用2 S$ N8 N! w7 @& ?4 s) X9 B9 a
3 q3 [4 W/ D3 Z$ S
5 l) |! D. r1 y6 H8 x# v
3.数据库3 x* P6 g4 b$ A, g
1.配置 连接数据库* _, |- O( E4 `# L8 h, i
代表驱动2 D1 [% g( V0 e: h! ]: \! Z9 P
MySQL-Python  # 可以写mysqldb: E1 W6 `: D" L: e: D7 J
    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>: E* R6 K0 ?3 u
) z1 Z( I& V8 H# y8 ^
pymysql
+ [- ]8 B/ S: F2 E    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]9 O# d1 \0 X: s
" K4 R3 S& f2 C4 Y3 m( D
MySQL-Connector
( J' e0 U3 n; U3 ~4 |    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname+ `  d3 r0 x  A! ~/ P: |; C
6 y+ V+ h3 F. v3 s/ u* g& @
# |& U% ]/ s) l) p
. D* m! V4 n% b& v/ S
需要安装不同的扩展 注意mysqlclient的版本6 a6 ?' X( R( i; Q
可以放到配置类里面( N; Y3 R& E0 z, W9 D. y6 }: b

2 D* q0 s' n/ `$ i2 y1 ^方法一
2 k" u- Q, @' x* |9 ?SQLALCHEMY_DATABASE_URI = 'mysql://user:密码@localhost:3306/库名?charset=utf8mb4'
5 U7 ^: P* [; t4 g* f- K1 {1 ~$ [. b: U; {/ Y" T* L9 I3 m/ v
方法二
' ~" F) h2 [5 [8 Y  wDIALECT = 'mysql'
2 ~  Z# A/ H# DDRIVER = 'pymysql'8 X/ E  X0 p7 o, b, z: A: Q  Q
USERNAME = 'root'# u' R5 u% C7 F! {3 J
PASSWORD = '****'
- @1 H( t' N# V: D2 B# q* rHOST = '127.0.0.1', n5 m$ o+ [. L: o1 w% Z3 ], d
PORT = '3306'
1 U; C8 E' E; z& _$ N+ o2 BDATABASE = '数据库名'1 L* ], F1 e' E" Q. o
- Q4 s: P+ C) ]
SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)
/ e2 s6 s7 B5 ^4 B9 D5 [; }+ I1 E2 K! ~- y# W) U

( O0 g6 L! j: Z! }' F/ p, N2.连接数据库
4 b. S, C% {( t7 c( J8 W1 实例化SQLAlchemy对象  可放入其他文件0 k* O$ S) S0 L/ v5 ?* u: E) X7 G
from flask_sqlalchemy import SQLAlchemy
! c: ^' i: f* I- ~. C* U. Idb = SQLAlchemy()
0 \1 ^8 t' j" V: N- Y5 h, J( L8 d
: ?! t- z6 `4 I- n" y2 注册db
$ E8 P* W$ G% l- H1 g
! m# o* K, M3 w2 T# 初始化迁移数据库
2 T2 d/ d* L- c' I9 b' u0 V  ?migrate = Migrate()
% Z' P4 C  p/ i6 X0 W1 j: |
/ u7 r5 l5 R" z4 Udef create_app() -> Flask:
1 {2 X  X9 ^: s0 D    app = Flask(__name__)
) m- l' a, Z' M4 R1 h4 U    app.config.from_object(Config)
9 w' ?; F9 @0 {, d- U    # 绑定数据库. E! I8 q: A% t5 ]
    db.init_app(app)
! ]' C: [4 S% t2 o% T1 r8 F
) ?- j# r+ B& |0 h& d6 Y* H- ]    # 迁移数据库# L1 o* Q# a$ n
    migrate.init_app(app, db)" h4 ]1 y9 p/ I. S: }# h" R0 X7 W
    return app
" @2 ?; {8 Y! T- d& y4 j" p
! z) [. P. F% X, Z7 r3 k" A- z0 H. b- F. \& N# y6 i
注意命令可能无法迁移3 ~- G5 z- t+ s. T* m
# G' r% Y0 Y3 P( m# L; Q- `  G! b/ T
1. 命令行一直报  & C* m6 o3 h. j0 @' X. X( i
# Error: Could not locate a Flask application. Use the 'flask --app' option, 'FLASK_APP' environment variable, or a 'wsgi.py' or 'app.py' file in the current directory.3 U+ }- K8 ^- O8 H  B5 n4 ^

: K" R4 A. l6 l9 g4 p这是在虚拟环境没有配置
% B$ F! t) O+ S8 V! |! V1 f2 b  ]/ p" J
% h$ o* Z, M0 V1 g! H( S使用 .env 文件 来设置数据
* a. K3 h; w  k/ N# 下载 插件, O4 G" K2 n# ?8 S1 U/ s
pip install python-dotenv1 S) a5 L' ], C( a# @% M

9 l6 B0 n$ X# B% t% }/ b: D# 创建app9 ?2 z& U0 ?" I1 A/ y  I$ i. f
def create_app() -> Flask:0 q' U2 t# q, h' j: f6 }& z6 E
    app = Flask(__name__)" V& G# H3 m6 Q$ T. F8 j* \( h
    # 要在最开始加载 后面才能获取到
! w: Y2 \/ [7 z6 Y# J. r! q/ V/ d+ H" g    load_dotenv(verbose=True)) U. j0 R1 r% n3 e% o

9 v; X( A' W% v7 t( P0 G    # 注册配置文件 生成/测试! M! U" r# t$ R7 H" V7 w
    # env = str(os.environ.get("FLASK_ENV"))
" M; }6 f4 D; i! C    env = str(os.getenv("FLASK_ENV"))
$ J% u0 u0 E% f$ c4 e4 G( b$ |5 u    app.config.from_object(getattr(conf, env))
: i  Z, ]% j' ]  T, h9 J$ L: B; }/ n. R  `3 W
    # 绑定数据库+ C/ n% V3 t7 p) e$ f) c( |- e( d$ k
    db.init_app(app)6 E$ n. W# E) A& @4 e

$ b" r$ A, Y- v6 Q0 Q2 ~    # 迁移数据库% _$ Q! }$ G" }/ _
    migrate.init_app(app, db)
7 W, `, B* U0 t  J( R/ |0 Z: l    return app
' o1 z2 ]4 X9 p. }8 k$ Y2 e$ k$ Y#-------------------------------------
: }+ |; `, x+ [2 f% W% d3 }# .env 文件0 C5 ~; ^9 M" u5 L# h

* y0 U1 R2 \8 sFLASK_APP=main.py # 自己的启动文件 默认是app.py+ F/ N8 O% r" U; `
FLASK_ENV=development* J1 U7 v$ Y& G- Q
FLASK_DEBUG=True  h& \5 L! B9 V2 e( w1 b9 Z
, K' `$ ]( R, r. _0 n; y

3 L* Y9 F+ Y/ g, |这样就可以输入命令了
6 C- x# F1 K' f- c
3 C+ C6 y( H6 f$ {8 D报错误 either 'sqlalchemy_database_uri' or 'sqlalchemy_binds' must be set.
! K$ q# i$ a, n$ f没有把模型放到 view文件里面 只想要把 模型导入就好了,可以不使用
+ f; g. F( a4 a0 [& O- jfrom user.model import User
$ g( _% v3 V. N3 ^- r: u) \3 ], x+ _9 j5 J
& V6 ?+ ?9 h7 V
3 迁移数据库' \' _9 L/ |' d1 A- e4 \6 E
# 初始化一个迁移脚本的环境,只需要执行一次。1 ~% [6 h, F1 [9 q% ?
flask db init) c1 ]$ s; C: c9 R
# 将模型生成迁移文件,只要模型更改了,就需要执行一遍这个命令
3 i# h* Y  `+ K, X% S5 zflask db migrate -m'迁移数据库'
7 l$ \6 \% @0 X& O! Z# 将迁移文件真正的映射到数据库中。每次运行了migrate命令后,就记得要运行这个命令。# d7 B  h8 G- P/ y
flask db upgrade
+ ?( n# _2 F- e+ f. G4 |) p6 E#-------------------------------------' }6 n2 U4 _3 D8 b3 y0 u% ]
flask db heads 查看当前最新的迁移id
8 C# W( T6 _/ pflask db stamp heads # 更新7 F" `6 D( k+ V  G1 p, J! Z+ F
flask db current  # 查看当前迁移id
( l  H$ @' [$ e) lpython manage.py db history  #查看历史6 w3 g' `' {* G6 C9 g. p8 K; F
python manage.py db downgrade 652a55840d  #回退版本
  f, g- ]* Y6 M3 v/ N& V' k2 g3 v& E/ u7 ^) s  p, t6 m2 A
0 _; `# U* ]" t6 p4 l( M  n: q
4 数据库其他信息
3 Q/ V: Z1 e; e# 查询时会显示原始SQL语句
* r% b# t2 `  l) I7 H! ^0 s! ^' rSQLALCHEMY_ECHO = True' k  c' Q2 W) {  x
# 动态追踪修改设置,如未设置只会提示警告
! n' H4 h: U  hSQLALCHEMY_TRACK_MODIFICATIONS = False
5 u1 N, b5 a* ~- Q! o# 数据库连接池的大小
- X. a; V0 M5 j$ ]7 y# Y( G5 }SQLALCHEMY_POOL_SIZE = 10
! y( U" U  @6 A1 Z& E: N8 T6 r# 指定数据库连接池的超时时间* i8 y: q  j) V  r& j3 H; s
SQLALCHEMY_POOL_TIMEOUT = 10
! a; I7 M, D1 Q4 |8 Z! I9 b9 f- y' o# 控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。# U2 r( z( d, G# M7 H
SQLALCHEMY_MAX_OVERFLOW = 2
- l/ o" H3 Q1 u4 P9 H
$ n& n0 C; L) R! g7 U" h5 [' Q( N" W; x
- P  Q3 S; h  b% H8 ?名字        备注
6 V( o! t5 }1 _9 ?2 p- |% D% X% oSQLALCHEMY_DATABASE_URI        用于连接的数据库 URI 。‘mysql+pymysql://root:密码@localhost:3306/库名?charset=utf8mb4’$ v/ j# S6 i' j' W2 l. E
SQLALCHEMY_BINDS        一个映射 binds 到连接 URI 的字典。更多 binds 的信息见用 Binds 操作多个数据库。
2 [$ K' \% l% t$ x+ F- ]1 Z# SSQLALCHEMY_ECHO        如果设置为Ture, SQLAlchemy 会记录所有 发给 stderr 的语句,这对调试有用。(打印sql语句)/ I. W" c) }% T" X/ z
SQLALCHEMY_RECORD_QUERIES        可以用于显式地禁用或启用查询记录。查询记录 在调试或测试模式自动启用。更多信息见get_debug_queries()。2 }3 k) O+ o- _3 N: L8 W' e7 P
SQLALCHEMY_NATIVE_UNICODE        可以用于显式禁用原生 unicode 支持。当使用 不合适的指定无编码的数据库默认值时,这对于 一些数据库适配器是必须的(比如 Ubuntu 上 某些版本的 PostgreSQL )。
8 m. v; C  L* h$ U7 MSQLALCHEMY_POOL_SIZE        数据库连接池的大小。默认是引擎默认值(通常 是 5 )
/ C3 ]0 M# Y& e5 U7 v8 T2 M/ D6 zSQLALCHEMY_POOL_TIMEOUT        设定连接池的连接超时时间。默认是 10 。
3 F  W" W) W# wSQLALCHEMY_POOL_RECYCLE        多少秒后自动回收连接。这对 MySQL 是必要的, 它默认移除闲置多于 8 小时的连接。注意如果 使用了 MySQL , Flask-SQLALchemy 自动设定 这个值为 2 小时。
" _/ N$ f' o7 J# z2 ?9 d$ g4 创建表1 s6 N) H. B! \! O
from core import db        #这里需要引入实例化的SQLAlchemy对象, d; _6 B9 s9 e1 l6 T1 V5 _1 `
3 |' m9 Z9 W$ Z, ]
class User(db.Model):/ D" |5 k$ e* O) G- n1 ?
    """用户表"""  |+ z$ f' |  q7 i' n
    __tablename__ = 'user'  # 创建后表名 小写
$ I' @. _6 R/ U' @; e$ l    # __abstract__ = True  # 抽象表 不创建这个表 可以继承
- |8 T& L, M9 ^; h
/ d# u: ?6 y% y% q) q8 ]4 k& H8 y    id = db.Column(db.Integer, primary_key=True, comment='id主键') # 必须要有
1 M7 d0 ^( u1 w5 _    username = db.Column(db.String(32), unique=True, comment='用户名')
. s' f* z7 Q! z  d/ z1 K. H  I    password = db.Column(db.String(64), nullable=False, comment='密码')3 p6 N' V. Y/ p& ]% q% W
    gender = db.Column(db.Boolean, default=0, comment='0 男 1 女')/ G: @  ?, [. d) v( \% p$ I
    avatar = db.Column(db.String(125), default='http://s5p.hd-bkt.clouddn.com/default.jpg', comment='头像')
1 Q# A4 x5 V, w) c! T& ]. b7 z% M    addr = db.Column(db.String(256), comment='地址')
: ?2 d6 f  T: X  N    email = db.Column(db.String(125), comment='邮箱')8 e, T: [' Q7 `- ]
    mobile = db.Column(db.String(11), comment='电话')! X* `, _' p$ T$ m4 p
    login_type = db.Column(db.Integer, comment='1 电话 2 邮箱 3 用户名'); }0 s" Z6 k. M- k

1 F( R" _( b, C9 E7 `$ l" `    def __repr__(self): # 查询的返回 和str一样8 L6 O. ]3 c% v% o
        return f'<{self.__class__.__name__} {self.username}>'! e5 W, X' Y& x# k+ }" w

& e: W/ p0 Z9 c
; X+ Q% w. L+ g- o. t1.字段解析8 z4 B$ u! V) J/ M  N- D. w
类型名        python中类型        说明/ z) D8 M  Z6 L& C) T6 R) w5 e
Integer        int        普通整数,一般是32位* ^* O2 m+ r$ _( W: H( y
SmallInteger        int        取值范围小的整数,一般是16位
3 i. @) o1 o  |/ `4 eBigInteger        int或long        不限制精度的整数
! v: k+ @: m9 s# O7 Y& U1 BFloat        float        浮点数
# @( ~1 |* m! \3 @  e( qNumeric        decimal.Decimal        普通整数,一般是32位9 D4 c% ~" Z/ g
String        str        变长字符串
2 B1 _1 y- V4 N. R, T$ h+ kText        str        变长字符串,对较长或不限长度的字符串做了优化
( V. D/ O6 t% I9 S. sUnicode        unicode        变长Unicode字符串
% K3 d4 K$ `. A) D2 C5 IUnicodeText        unicode        变长Unicode字符串,对较长或不限长度的字符串做了优化
. z# D) l5 f& g8 WBoolean        bool        布尔值
" h, N3 |6 U- n4 G9 d/ B% Q- FDate/DateTime        datetime.date        时间
/ X/ r0 V2 Y$ k- o: tTime        datetime.datetime        日期和时间) A+ N" S4 ?0 c" f! _1 m! u( q
LargeBinary        str        二进制文件
2 V( d8 a4 N5 J$ @2.表属性
9 ?- Q/ n, i: U: S5 A选项名        说明  c' D/ b- Z( I- S
primary_key        如果为True,代表表的主键1 e  V1 X5 o& ], T
unique        如果为True,代表这列不允许出现重复的值$ A" E: j& K) \4 [4 Z( r  H5 Z# a) Y' z
index        如果为True,为这列创建索引,提高查询效率
  D7 [9 f! I) s2 a: snullable        如果为True,允许有空值,如果为False,不允许有空值
: h5 I! o! H$ k/ \3 F9 K) ~  tdefault        为这列定义默认值7 s6 P* D. m2 W1 b; h* x" G
5.查询0 e- D& J- j5 }
注意只要对数据库操作就需要 db.session.commit()
4 T7 n$ v7 ~/ k& K3 _
4 D6 C/ b. g; h2 }查询方法
; R4 @3 l; X) p方法        说明
+ U3 m+ P) o9 r; Z: E( vall()        以列表形式返回查询的所有结果: {2 n5 c% y4 b! e9 G
first()        返回查询的第一个结果,如果未查到,返回None: I7 S( }, a! Y  U- y7 p9 f/ [" D
first_or_404()        返回查询的第一个结果,如果未查到,返回404
5 G) u: k# O0 hget()        返回指定主键对应的行,如不存在,返回None& n7 Q# P9 p' _/ e- Y' ?
get_or_404()        返回指定主键对应的行,如不存在,返回404
9 `" k( S$ F% gcount()        返回查询结果的数量2 v& Y6 S' S! t5 `% [
paginate()        返回一个Paginate对象,它包含指定范围内的结果
8 |! U; S8 O2 ]$ z$ o9 H1.普通查询
! L# {: y& \( W2 R: i- w5 d# 查询数据条数( G7 I/ T: H2 ?4 _
User.query.count()
, u; \; c& J2 |, R
+ A/ Y' F6 L; x$ u/ H+ Q8 Z) E# 查单条 获取不到none
; l; ]8 P% j0 U1 y# p1 Ouser = User.query.first()7 N8 S3 d$ x: K  i' ^; |: o, D8 J
user = User.query.filter(User.username=="小红").first()* [/ v. S9 x' N4 I# t) v
user = db.session.query(User).filter(User.username=="小红").first()4 E5 _: k# S6 M
'''' q+ n; }. q( f2 L$ C/ a6 H
db.session:是一种更明确的查询语法,适用于更复杂的查询场景,或者在不直接访问模型的情况下执行查询操作# O4 L, j9 e  p! k
'''
) C( _1 E# M5 ~$ _: P9 F0 O/ M6 |" g% v0 [" e
# 查所有9 z* n( `, Q1 W' S4 e$ r" C9 K! d
user = User.query.all()- G" l' H; ~5 t! F6 r9 H+ r; X
user = User.query.filter(User.username=="小红").all()
  K" f" {6 c( ?1 Guser = db.session.query(User).filter(User.username=="小红").all()3 h' y; \8 l4 z% T  U
# D  h5 }& B& ^# a0 v6 v7 ]8 x
# 只获取单条
: R/ M0 L' [; ~! E: b' f3 a# 结果为一个时正常,多了就报错
9 H2 W* d$ Q+ q# one_or_none() 获取不到报错) S; S7 q/ U% {4 G5 S
user=User.filter(User.username=='小红').one()
* u: l# M( {$ y9 g' G4 V0 Z  R8 G# r* c- I' v
# 获取不到报错
+ d# a7 x4 _2 M$ v/ M# get里面需要参数 是id, H: i% C& F. Z0 Q/ ]
user = User.query.get(2)+ k1 G4 v+ |; ^& @% t/ T% W! P
2 E3 y2 K7 j0 _5 `
6 Q7 z5 R+ a- C+ l7 b

" t# m% M$ t7 w2 w2.条件查询2 M& G: m( O2 K: B' x$ X: N8 A
# 条件查询) @/ v- H/ E+ q. ]9 u  U$ O( C
  user = User.query.filter(User.username=="小红",User.password=="123").first()
: D. D7 s/ f: o& j# 不等于
( _0 i2 K8 r$ U, f1 C! g  user = User.query.filter(User.id!=2).all()
4 B4 R# O$ n- @; {4 A# 大小于
& w. }( x4 `8 S) l9 @1 B. ?/ i, H  user = User.query.filter(User.id>=2).all()
' b8 @5 G$ p- t# y2 x7 Z1 h  user = User.query.filter(User.id<=2).all()( e" u9 d" \; w- C* O

7 G8 ?( W! t8 c" _5 G#----------------------------------------" h4 r1 L. H- `4 a$ R
# 结尾为红
4 j, d9 b; Q" E1 s; F$ kUser.query.filter(User.name.endswith("红")).all()* q0 C3 w1 B( D" Y* l2 z
User.query.filter(User.name.like("%红")).all()# v" ^: [+ @; w+ t% f* B
# 开头为小  u- s5 t4 p/ x8 ?' E. m
User.query.filter(User.name.startswith("小")).all()
7 d6 n8 Q$ ^* Y8 Q/ r6 b0 IUser.query.filter(User.name.like("小%")).all()! q* `6 M- w2 f1 \$ Q
# 包含n mysql语法
! t" j" \7 W/ g. S) {3 _5 @( TUser.query.filter(User.name.contains("n")).all()3 Y; x% L% k* B+ Y! P% E; e- j
User.query.filter(User.name.like("%n%")).all()  # 模糊查询
3 u0 j* m, c' c) P2 e7 W, q3 N, z9 V6 L6 }7 @% q9 a  z. x8 `, o
#-----------------------------------------2 B7 X) b7 b- p! |8 n: V& ~4 D4 w8 X
# 成员属于  in_' Z: f" s3 T6 j% A
User.query.filter(User.username.in_(['aaa','bbb']).all()' |9 q( b5 S8 U6 a8 Z
#成员不属于  notin_: T& V1 b0 w6 D! Y" a
User.query.filter(User.username.notin_(['aaa','bbb']).all()
  a5 j8 p. U0 {4 D) D* D' s+ _2 C* v/ J5 R" m
#----------------------------------------
, g& P' u6 L3 a3 pfrom sqlalchemy import and_, or_, not_& |( ]* i- o1 c% C5 [- U  m
# 和
% }: X! a! I8 e6 pUser.query.filter(User.name.startswith('a'), User.email.startswith('q')).all()
8 q  @8 h/ N6 t: |# A" ]$ HUser.query.filter(and_(User.name.startswith('a'), User.email.startswith('q'))).all()- \0 S* s8 i+ t) @1 b) r5 R
# 或者, M4 }( S' `& Y, Q
User.filter(or_(User.username=='qaz',User.password=='qwe123')).all() , U  [* U( [, H; v5 x( B- C2 D
# 非
$ J+ x. i) W* j: B& N0 `User.filter(not_(User.username=='qaz',User.password=='qwe123')).all()
% D# ]* j0 G6 i. Q2 T4 m+ Y, K. ?6 Y  n( L! H
#是否空判断# Q0 T  }) M4 G0 X: i% V
User.filter(User.username==None).all() )
% L! o% h, h* c  q7 NUser.filter(User.username.is_(None)).all() )
! ~" W! ^# j- E1 XUser.filter(User.username.isnot(None)).all() )
, j: [* M3 [, m/ L6 A/ [  B$ U. L
#------------------------------------------
, B. \& J: Z' A. \9 L" v3 |# limit 限制返回数据条数
. e9 b8 {/ e. B% q0 E8 J' @6 U# 开始条数是0, b- A5 E. l' ~# }8 u) o* r
User.filter(User.gender!=1).limit(2).all())6 `- Q9 ?. l* m& J/ m$ H+ P
# 从第几条开始获取 偏移5 \3 S7 ^3 L' R! K
User.query.offset(0).all()
1 A& y6 P* g" C( I' @# 从第2条数据到第3条 包前不报后
0 f2 |6 H) A) [. nUser.filter(User.username!='qq').slice(2,3).all())& Q* L' @# X& }# u; b& u

* W  n" Y5 m; ~7 ^+ K! x3 q# 排序 order_by 默认正序
) V! C  `4 s, ^' ]8 ? User.filter(User.username!='aa').order_by(User.username).all()
" G' q" u$ j# w4 W# l* x User.filter(User.username!='aa').order_by(User.id.asc()).all() 正序
+ Y6 H1 @8 D' A User.filter(User.username!='aa').order_by(User.id.desc()).all() 倒叙
" B0 v0 {/ N& S( O- O; `+ Z+ v4 [) R2 N: R. X) ?
# 注意:上面的可以随意组合7 g, h6 e! H9 Y: W
# 其余后续补充
) u! b' j$ h# }) O6 J( }$ o/ @. M  }7 c7 C8 B% {

! w" S' C/ ^4 |3.filter和filter_by6 X( g, v( H6 `
filter_by和filter都是过滤条件
" L$ P+ S# X. k5 A0 f  Y  J; ]filter_by 不支持比较运算符,只能用=
7 T8 x8 j2 m" l, }. c* e- q! I# Q% _. z' E% W
# 返回的都是对象
6 h& ]5 d. ^4 p. ~. L% mrows1 = User.query.filter_by(username='小红').all()
9 `" F0 D( d% ~  w, x( mrows2 = User.query..filter(User.username=='小红').all()
+ Z) x* V' A0 J/ l( z
; L0 K: ?" d6 g% T- p# rows3 返回的是User的username属性,不是对象: A0 a$ @5 _; b! f& v! J
rows3 = db.session.query(User.username).filter(User.username=='小红').all()& r' m0 M/ A* q9 b: M0 y
# 返回的是select语句
! S* P" k2 g, x6 [% ]rows4 = db.session.query(User.username).filter(User.username=='小红')% a& L# I; B; D: ?- d0 d% j
6 D' T  {3 P& b; j( r, o

& E* j4 M- A) f) k0 k7 F$ y  b6.增加
! Z; w) W: l: {$ w( l0 ^9 x( ]6 `# 单数据增加  
( ?; W+ @- V' m* E% P  user = User(username="张三",password ="123",email="123@qq.com")1 `6 P5 n0 n; j- e! S* Q3 q: y+ t: }
  db.session.add(user)
7 w& a) W2 a5 O( H6 e  db.session.commit()
/ C1 c# i3 n1 ]6 T0 g1 _
7 S1 B  {4 U" l7 f; w% n, G#-----------------------------------
: d$ X% K, ~& u4 y8 q5 \0 e# 多数据增加
% t: D8 }0 X" k4 Y+ s& H/ [# 后面两种可能会有颜色警告" X! z) W, C0 I5 o7 }8 B# ~
方法一:使用字典列表一次性插入多条数据
4 m8 q- H; q- t) s7 F0 L@bl_user.route('/index')
6 T  b9 b* J4 k* U! jdef index():
& I1 n& j$ p% q4 ]! }4 n% V    data_list = [0 X* I# ~6 B3 x8 t
        {'username': 'value1', 'password': 'value2'},/ x5 v: |) T  h. `" L. g' P# O
        {'username': 'value3', 'password': 'value4'},
1 @9 z) v% ?, X* ?4 C5 D1 M    ]
, V+ i9 H8 k4 f# a5 d# T    db.session.bulk_insert_mappings(User, data_list)) Z  H. O. X& O
    # db.session.bulk_insert_mappings(模型, 数据)) U9 M3 B% ]! r; E& j6 `
    db.session.commit()
1 O- r+ j3 L4 e# f% V8 M2 Z    return '增加成功'
1 l& s8 `9 ^) Z2 }9 e/ F$ \8 ?7 L8 E. ?
方法二:将多个对象一次性保存到数据库
$ g( m# r& r  v8 C8 @" m' P$ U@bl_user.route('/index')9 M# D) o! H  [3 q
def index():1 k) o" O: E/ C5 K. a1 ~* Z
    data_list = [
" {  @9 _% u3 i        User(username='value1', password='value2'),
1 C" J: M# T2 F  {& v" u        User(username='value3', password='value4'),
- y! R, n1 T* l4 S* C: ~    ]3 r3 S. D; H: U0 G5 p2 R
    db.session.bulk_save_objects(data_list): y2 Q7 P/ D+ u
    db.session.commit()) M! ^6 I* f. i3 Q9 \1 x9 H
    return '增加成功'
/ y3 @; O. `: @5 n4 r
7 @% o* T: }, ~6 B方法三:0 x. \6 i* c, Y' a* M& L
@bl_user.route('/index'), K# l9 u- J: q' H+ G9 _# i% k1 O  K
   data_list = [3 r% r  D( T# t. x, {
        {'username': 'value1', 'password': 'value2'},+ G2 c& c; @( {& S2 d
        {'username': 'value3', 'password': 'value4'},8 j6 b, E% l' ^5 N$ K
    ]
- H/ l* Y) F  q  f2 F" d  @  z4 Y# t2 R, H4 Z
    data_objects = [User(**data) for data in data_list]
5 L. r' x0 G3 b. [    db.session.add_all(data_objects)
  ]/ D* P# `' j! q9 ~. L    db.session.commit()& C- U1 H" o% L) P! j+ |
    return '增加成功'
6 }, Z8 ^9 G1 S( u
# \1 K: _; @. ^* {, `8 v! B2 E* x: Y/ c6 m- u
7.修改% p$ Z; U+ g1 X
方法一:先查询后修改 可能会丢失数据
7 [4 o$ b# b! ?& V( s1 yuser = User.query.filter(User.username=="小红").first()9 V! b; W- h) @* P
user.email = "abc@163.com"
# S9 z; j( f  }" x. Zdb.session.commit()
7 s6 f  F9 C; r) s  }5 g
% n% w) c/ l& w  e$ {) }6 }/ ^方法二:直接修改 推荐
& i" w' _- N6 F, @5 [; @3 dUser.query.filter(User.username == 'qqqq').update({'email': 'ABC@qq.com'})8 U( A! C" G0 Q% }% v9 f, {2 o; p
db.session.commit()
3 e" Q: v% P( r: M
6 ^2 N: }  e. g#--------------------------" _4 s' W: K" k! U1 ]* {
# 批量修改 列表套字典. T* J, z/ S* r
# 注意必须要有id 确定修改那一条
5 U6 D  {- s+ c: G. V/ T    user = User.query.filter(User.id == 1).first()3 W2 ?7 R6 K6 F! V  q+ f1 |
    data = [{'id': user.id, 'username': 'zzzzz', 'password': '12345678'},( d% B1 V; Q  m9 _+ {) E
            {'id': 2, 'username': 'aaa', 'password': 'zxcv'}]2 ]' a/ a4 c& V2 O6 z9 O
    db.session.bulk_update_mappings(User, data)7 ]' Y5 p9 G) \' n
    db.session.commit()
' `" [- Y  N; [. Y0 i2 w8 W) B/ o1 l5 z  J5 K  I2 @

, k2 M: }: ^8 r& ^7 |8.删除% q: k0 M( l( T* P6 \4 G6 |: U6 B
方法一:先查询后删除 推荐
- h+ c* x, V. I. duser = User.query.filter(User.username=="小红").first(), ^8 ~/ e6 T( Q( w( I
db.session.delete(user)
4 t$ h: {1 a8 K" Q: T9 y- @db.session.commit()! I" ?/ `7 v# n

. L+ R7 z' {7 T' r3 }: `# w方法二:直接删除 可以删除多个
. r2 a' P# k, W. J  duser = User.query.filter(User.id == 2).delete()3 R2 [1 ~' a: h# X
db.session.commit()
- Y% K: c2 A: B: L! C' x
( {! z5 H) w4 Q  ]3 C& j# 假设有多个xxx 那么就可以把xxx全部删除" x4 h0 n# j2 T' S3 J! K
user = User.query.filter(User.username== "xxx").delete()
% q4 t4 \- e! K( A, y" Qdb.session.commit()5 X4 c# S  o0 g3 }% b
cv'}]8 ?8 ?6 Z: p  e( o1 q
    db.session.bulk_update_mappings(User, data)
9 V! v! x' e' U, R$ t* r    db.session.commit()$ ^- a4 m. s9 N' e* Z9 ]

2 ~( ]# \, ^6 @( c9 [/ d7 t2 U5 U2 o. D+ w1 l; [; I" h' I3 \! Y+ A( W
8.删除  C2 H. N. e0 i) t- @, M, s' {/ Q1 W
方法一:先查询后删除 推荐( X4 g* l% ?8 e2 ~$ `
user = User.query.filter(User.username=="小红").first(); i7 {/ X" I# q8 h9 n
db.session.delete(user)
) j' k! B5 b& {' Edb.session.commit()0 Y4 W! ]8 K2 N. q

$ ^4 x$ B! g9 d; h! ^9 h' @" J- n方法二:直接删除 可以删除多个# }, T" S7 l  T5 K  T6 Y7 l
user = User.query.filter(User.id == 2).delete()
7 |: k- A) v: A" H# O/ x- Edb.session.commit()
  n7 Y. V0 @% k2 F1 T% ~. `% G! N8 i& O% a' I$ N
# 假设有多个xxx 那么就可以把xxx全部删除! v7 |8 A, O# s3 P- C
user = User.query.filter(User.username== "xxx").delete(), V) R* L" _. z) |' x1 J& o
db.session.commit()
5 G5 Q- d2 A3 j3 ]) Q: P3 ?* \0 M+ c2 [* f
6 Y6 ~: N9 c1 x9 H3 k

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-7-30 22:52:09 | 显示全部楼层
A Simple Example- P5 S, @0 d' d$ _
from flask import Flask
/ r& q0 X% Q2 e. _8 sfrom flask_sqlalchemy import SQLAlchemy
8 D$ T! A- e% m3 Q0 {5 A' M' x+ Pfrom sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column- a3 I8 g- Q8 X

# q& o# v/ ]; iapp = Flask(__name__), f$ {, T: B, P* W7 s" z) x. o
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.sqlite"
! Z1 ^/ o' r' }1 h. X6 K7 w% K8 `3 N* ?
class Base(DeclarativeBase):
* X1 h- \2 u8 N5 M+ ?2 L  pass% @) D) e0 s# a) R
  J% I" V/ T" ~% a
db = SQLAlchemy(app, model_class=Base)
& o5 h7 E1 m4 e1 X' R1 V. U& }- s+ }4 j& G7 \6 \& n
class User(db.Model):
7 g9 W. D' n( h    id: Mapped[int] = mapped_column(db.Integer, primary_key=True)' @! q4 a/ Q4 h9 {0 R
    username: Mapped[str] = mapped_column(db.String, unique=True, nullable=False)% {) R# J. L1 L  a3 S" x
1 |. r* E% [; \/ f/ j
with app.app_context():
7 C: m7 _( B  n* g& m" |    db.create_all()1 w, D" W  Q- O8 F0 @( V( f
$ h' \8 x; B1 v5 _' X" s" |
    db.session.add(User(username="example"))
( w' J% G. i" n6 {3 f2 Y7 y    db.session.commit()
! T; i! C% h4 ]& O% T8 [- ~# P) \* l% d3 `$ Z
    users = db.session.execute(db.select(User)).scalars()
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 01:32 , Processed in 0.027615 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表