易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 29|回复: 1
收起左侧

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

[复制链接]
发表于 2024-7-28 17:00:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
1.介绍* ]6 d/ s& z. T
flask用于orm操作表,一般使用flask- sqlalchemy 操作简单: J7 V, K2 b7 e0 `
一般使用flask-sqlalchemy 2.5.1
3 I' y. t1 p) F% d: [* Phttps://flask-sqlalchemy.palletsprojects.com/en/2.x/2 N4 o- |; T2 i; B

2 k/ d2 s/ w+ M
' N8 W# B! X6 e/ \3 l
6 r& J. {3 O" @1 l2.安装
3 |7 t# m/ L8 t" c! j" Fpip instal flask-sqlalchemy==2.5.1
7 U) e5 b7 R8 ?# Opip install Flask-Migrate==2.6.0  # 迁移数据库使用
$ q" X6 d4 v4 Z. I' ?& d( W
; `0 o, I4 E3 K
; U) S, @: M% m6 P3.数据库5 P4 K* [- ]% D3 N% F
1.配置 连接数据库
; `6 y7 R1 y( w( t7 \8 }/ ]代表驱动
& g) O- R/ U' j8 U  W% vMySQL-Python  # 可以写mysqldb
# ^' Z6 u" S  R: ~    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
( y( N& l6 L4 x* l( q3 S4 U, d  D) m$ F- q7 z8 H2 \! ?* e+ v
pymysql! ~8 f$ u9 N9 l6 `( X% S7 t
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]" g$ u; v$ v; B# c

: J' g% Q) C& |5 l4 kMySQL-Connector3 J0 F9 X9 T4 m9 w
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname
; c+ ~2 Z; ]- E' D  o
5 v: @- \; B* R& [
1 v+ I/ e0 b; q/ l1 |% b. w0 B$ {) y5 p; t
需要安装不同的扩展 注意mysqlclient的版本" L# e+ p4 Q* @0 u0 Z) i
可以放到配置类里面
9 z. L- j2 S/ a$ W
9 \- d% ^( H9 @; C/ G" `方法一
/ {- i  }  s! w% r0 R- USQLALCHEMY_DATABASE_URI = 'mysql://user:密码@localhost:3306/库名?charset=utf8mb4'
$ G2 C. p7 R3 V0 X; G  K0 `
& H- B3 ^% j" g: v方法二+ h0 l8 ~& h: P9 i
DIALECT = 'mysql'  S$ N- U9 u& _/ U
DRIVER = 'pymysql'
' t, [+ P* r! k- }& r5 ZUSERNAME = 'root'
$ L% W+ {8 C; u9 B2 ^! SPASSWORD = '****'
/ @5 ^: k- |) aHOST = '127.0.0.1'
( Z, c- |# L/ s9 c2 M2 t* I/ vPORT = '3306'
# d1 i' t" f% [3 D# hDATABASE = '数据库名'% B) |+ ~$ t4 B
9 a& J1 K2 h; k7 o" t
SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)+ B7 z! B7 I* v% L1 G( x
7 g6 D) u# h( R' V7 ^& x( ?

& j& {$ i0 |2 w" m+ S2 T; A; z5 K2.连接数据库
7 T9 @4 a' ^  R' R* F1 实例化SQLAlchemy对象  可放入其他文件: p" _  @6 d4 E
from flask_sqlalchemy import SQLAlchemy& S( N$ Z( M+ r0 {' Q9 \5 H' T
db = SQLAlchemy()- M( W( c7 J% |& z0 u2 `% R

# W4 d/ ^. S2 V8 h& v- f, E" l2 注册db/ C6 R. C/ p* d1 ?5 R
# h. h2 ^6 r% F- j
# 初始化迁移数据库
$ p7 P' O6 W$ P  Pmigrate = Migrate()$ b6 |9 U$ V! u, r

- e; r+ D1 i" |  J+ [def create_app() -> Flask:
$ c5 U; s6 A1 T    app = Flask(__name__)
- O( H0 K# V# v6 N+ ^. [    app.config.from_object(Config)5 h1 _7 k9 M8 A. j1 b
    # 绑定数据库
# p9 y  G7 M  c. r+ L! X$ c    db.init_app(app)% J+ B/ L' H, K
) q$ G( Y. \: ^+ g
    # 迁移数据库
& q9 V% t+ h+ w4 f0 C$ d3 ?2 j    migrate.init_app(app, db)
4 s. x" l4 x6 E8 q& Y, r    return app. I4 v  w: R% r. z/ {# ?
# i8 i6 t  {5 @( Q4 g- x. K! Z: E

$ _  ^9 ]: D3 B' l; d注意命令可能无法迁移: j* O% N# _- M; c: I& Q6 O2 m) E9 B
& F7 L# b3 A! J# R
1. 命令行一直报  
2 d9 o5 ?, i3 W3 m# 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.2 D  L( [0 k5 u: O$ H9 P

; T4 G# f$ m* e; M2 C  n" I这是在虚拟环境没有配置
5 D2 a* e4 }* ~: J# f' ^# S
( X. I6 s4 t1 l使用 .env 文件 来设置数据  x+ G8 e, R: A" [, m. R
# 下载 插件
  _" p8 ^0 J5 C' c' }* ]: |' Wpip install python-dotenv
- o7 A# R5 I# [# n1 V" w, g: r) r& t
' P" M1 h/ F9 Q. E3 d' k7 N$ Z# 创建app
; X! U. g, \; jdef create_app() -> Flask:
/ Y5 f$ W* S# Y& e" c% G    app = Flask(__name__)
( L! Y1 E; {. {& h: a& N$ q$ N    # 要在最开始加载 后面才能获取到$ F) i7 B" k* p. @
    load_dotenv(verbose=True)1 Z/ Z8 m. |' @3 p" g8 g
4 f+ Y: ?; D* D2 r- K3 o$ ~
    # 注册配置文件 生成/测试% c! g- [' i' u* s8 }
    # env = str(os.environ.get("FLASK_ENV"))
/ x4 k: g4 m' I" s+ ]    env = str(os.getenv("FLASK_ENV")): [' F& A; Y% I1 ~4 F
    app.config.from_object(getattr(conf, env))
4 ]8 W; u: I1 E
% ^4 Y! E, r4 |. |) p. P8 p    # 绑定数据库9 b/ _% E0 f0 B* @" Z3 X
    db.init_app(app)
: U" q9 T( v) C( ~6 O5 e5 v( O8 ]$ x. f/ E
    # 迁移数据库- x) l" n; K3 s! P& C
    migrate.init_app(app, db)
; Y( ~) r1 M! o  z    return app! v: l5 G3 X9 Z8 ^
#-------------------------------------
* f7 b- Q, E% o# O0 z# .env 文件
' z# q4 d( X4 m" m, h8 o! @$ G" l+ t
FLASK_APP=main.py # 自己的启动文件 默认是app.py
. P; p0 v+ l2 Y! ^6 l& dFLASK_ENV=development
8 c% ^3 q' A1 sFLASK_DEBUG=True
( {7 Y6 i7 d8 j  \3 F+ [  S- D* V# ~  z( F% |+ K- q  \; k& \
+ E+ I- [- E" y. Y2 A2 P1 m% y0 F
这样就可以输入命令了
. f$ b  `! |, V2 Q% J, K& j, a* S  h2 Q* N: S8 s
报错误 either 'sqlalchemy_database_uri' or 'sqlalchemy_binds' must be set.
+ W, v+ N2 @2 E1 x& I没有把模型放到 view文件里面 只想要把 模型导入就好了,可以不使用
/ h2 p$ n) S) G& T. o* Mfrom user.model import User9 |  I! f8 t3 P" }2 s' A' V

$ V$ T* i( F9 Y$ F1 ?
( X  c; ~4 Q; ~2 [! S+ `* E" P; K3 迁移数据库
# f( }1 w- l5 }' v9 F# 初始化一个迁移脚本的环境,只需要执行一次。; S8 m4 a6 H, @4 T# q/ M6 S5 M9 Y
flask db init
) A9 _+ b# |2 L+ f1 C# 将模型生成迁移文件,只要模型更改了,就需要执行一遍这个命令
1 d, c2 I" ]' q  w( m0 G* wflask db migrate -m'迁移数据库'
- v) t3 o( q0 C" g# 将迁移文件真正的映射到数据库中。每次运行了migrate命令后,就记得要运行这个命令。
2 P7 _, _" s! k+ P: ^$ ?flask db upgrade+ U6 C9 }8 J, b# x9 @+ b
#-------------------------------------
& R& F8 x7 \$ Y/ Eflask db heads 查看当前最新的迁移id
! T( x+ u' G- D3 y6 }- K( H4 D/ Q  cflask db stamp heads # 更新, h: `& Q( W% R5 r
flask db current  # 查看当前迁移id6 C0 Y& f; V8 o  X3 T
python manage.py db history  #查看历史
8 v! Y9 r) v4 l) m7 _# g3 Ypython manage.py db downgrade 652a55840d  #回退版本
; c4 {( [5 M7 a9 @0 M. V  F
1 y% ?9 G4 ]1 N& Z' K* T8 u* b# N" j
4 数据库其他信息, [8 B$ l4 Z4 @4 X- T- k
# 查询时会显示原始SQL语句/ w* q- f* R: A# s: F* G* s
SQLALCHEMY_ECHO = True
# M5 u! e6 X( M- L, x# 动态追踪修改设置,如未设置只会提示警告
- z+ H- J$ F: w" DSQLALCHEMY_TRACK_MODIFICATIONS = False
; O- c1 _% p1 b) P  o8 c# 数据库连接池的大小* C+ Q. d0 \2 z4 p" s
SQLALCHEMY_POOL_SIZE = 10
  U$ e* N& T  B5 m- d5 g- X3 C: t# 指定数据库连接池的超时时间) N3 a8 k3 k8 b9 _3 b2 }+ I
SQLALCHEMY_POOL_TIMEOUT = 10
/ N6 @& g+ D* `: r" \! C" _# 控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。3 }# B3 Z) }2 G$ [* E/ o
SQLALCHEMY_MAX_OVERFLOW = 28 z; Q& w1 y8 G* o
+ _6 ?2 Q' N; E0 x0 [6 L, q* y* G6 C
8 B* f) h. x, f) ?7 }
名字        备注
8 `0 `- k! s/ y# q& r4 g. n- oSQLALCHEMY_DATABASE_URI        用于连接的数据库 URI 。‘mysql+pymysql://root:密码@localhost:3306/库名?charset=utf8mb4’
( L( T3 Y6 N! ~# B* l5 x- ]  E' bSQLALCHEMY_BINDS        一个映射 binds 到连接 URI 的字典。更多 binds 的信息见用 Binds 操作多个数据库。7 q% E' a1 v1 b: y) R
SQLALCHEMY_ECHO        如果设置为Ture, SQLAlchemy 会记录所有 发给 stderr 的语句,这对调试有用。(打印sql语句)8 `  O1 }  b, W# d
SQLALCHEMY_RECORD_QUERIES        可以用于显式地禁用或启用查询记录。查询记录 在调试或测试模式自动启用。更多信息见get_debug_queries()。; O7 u. x" s/ P
SQLALCHEMY_NATIVE_UNICODE        可以用于显式禁用原生 unicode 支持。当使用 不合适的指定无编码的数据库默认值时,这对于 一些数据库适配器是必须的(比如 Ubuntu 上 某些版本的 PostgreSQL )。3 u8 y2 X" _. H2 N4 _
SQLALCHEMY_POOL_SIZE        数据库连接池的大小。默认是引擎默认值(通常 是 5 ), z7 @; c% ~+ Z( M$ B: Z3 M# R
SQLALCHEMY_POOL_TIMEOUT        设定连接池的连接超时时间。默认是 10 。% l" \  |' [  J% s3 ^7 d  |9 J4 i
SQLALCHEMY_POOL_RECYCLE        多少秒后自动回收连接。这对 MySQL 是必要的, 它默认移除闲置多于 8 小时的连接。注意如果 使用了 MySQL , Flask-SQLALchemy 自动设定 这个值为 2 小时。
) T9 e5 b* T& e+ v( j* q5 Q4 E4 {( J4 创建表
$ n  @: Y3 S$ \, B1 I; Zfrom core import db        #这里需要引入实例化的SQLAlchemy对象. I8 B7 h% Z! d" L( [& c

! J& I8 M4 j" U& a, Tclass User(db.Model):
6 d3 @9 f# Y/ O+ O  w% P    """用户表""". E& Z9 H" g4 l& H* l5 i7 A
    __tablename__ = 'user'  # 创建后表名 小写+ }$ s$ K' F  O. [  W; Z1 a7 h
    # __abstract__ = True  # 抽象表 不创建这个表 可以继承' p& V" P% ?6 e3 R9 e

& n1 g6 S$ B; r1 w. k* R$ f: j7 |1 r    id = db.Column(db.Integer, primary_key=True, comment='id主键') # 必须要有; P& B2 u9 q! d1 Z
    username = db.Column(db.String(32), unique=True, comment='用户名')- m  Z& l( m! ?
    password = db.Column(db.String(64), nullable=False, comment='密码')! V/ U+ F* [1 V' A
    gender = db.Column(db.Boolean, default=0, comment='0 男 1 女')
$ ~; L. G2 Y. e. }$ O8 \    avatar = db.Column(db.String(125), default='http://s5p.hd-bkt.clouddn.com/default.jpg', comment='头像')
4 U3 Q& K* C. T9 M; x6 E2 `1 @- x    addr = db.Column(db.String(256), comment='地址')7 g! r4 b0 N8 p' Q
    email = db.Column(db.String(125), comment='邮箱')/ p" P- p1 l* m& S6 T
    mobile = db.Column(db.String(11), comment='电话')$ |) I9 E: y' S/ [
    login_type = db.Column(db.Integer, comment='1 电话 2 邮箱 3 用户名')4 s* i& r6 Y* o0 O# E
: G3 {8 b) M- T1 J+ n) c1 K. d
    def __repr__(self): # 查询的返回 和str一样: q! Q7 D8 }0 m$ E" ~
        return f'<{self.__class__.__name__} {self.username}>'
& z5 J" e+ U4 r- F0 ?8 l2 k2 U8 j1 S& x3 l3 E1 v

+ C9 k+ [$ D# c1.字段解析" L: q) W  b. D# w7 N- ~
类型名        python中类型        说明
" k- k3 h0 ?. D% i8 [% [' SInteger        int        普通整数,一般是32位% q; k2 H' u9 c& f) z
SmallInteger        int        取值范围小的整数,一般是16位
6 t9 g* C. F8 v- N- WBigInteger        int或long        不限制精度的整数
. h$ l3 \9 d* Y! R3 y( B' g% q& EFloat        float        浮点数9 {; ^; [: Q% }. K  P  J
Numeric        decimal.Decimal        普通整数,一般是32位
% B" i+ k8 F0 D7 ~5 Q9 {9 N; qString        str        变长字符串
3 p7 {& D9 W+ aText        str        变长字符串,对较长或不限长度的字符串做了优化
7 @2 M3 X( {& v7 {- ^. t/ nUnicode        unicode        变长Unicode字符串
: T( y* \3 z& ~: h3 `UnicodeText        unicode        变长Unicode字符串,对较长或不限长度的字符串做了优化
$ H& B' H- V1 J, x* N( jBoolean        bool        布尔值
* o- P. y, W0 g' l+ kDate/DateTime        datetime.date        时间% ^* A( O& P7 |! k6 `/ _* I6 u2 r
Time        datetime.datetime        日期和时间: M6 s5 c' `2 y
LargeBinary        str        二进制文件% z; o* h4 Z' B* {) U
2.表属性
) \6 w' a2 N: I, q' S" x! V选项名        说明
4 R+ U. Z7 I: G3 P) f! Mprimary_key        如果为True,代表表的主键
0 P. r& W& l0 A2 r/ X  u4 gunique        如果为True,代表这列不允许出现重复的值
) b8 ^, B1 w* pindex        如果为True,为这列创建索引,提高查询效率
- F2 {+ Z8 n' F/ P4 P' w8 bnullable        如果为True,允许有空值,如果为False,不允许有空值
9 e9 Z/ ?1 A& L# z" L( tdefault        为这列定义默认值2 f0 r8 M9 _. N' v  p$ c8 ?5 I
5.查询
" G) \) ?5 q" _- J9 E  B7 a. f注意只要对数据库操作就需要 db.session.commit()
7 D7 D& z3 k) W, [1 S4 e9 C1 w
# O2 E$ S) ^' S查询方法# F) i' f6 m6 d. h" j) _
方法        说明1 Z! d: I$ U3 b+ k% R% _* J
all()        以列表形式返回查询的所有结果" N3 X; [4 P. r( R, D& H
first()        返回查询的第一个结果,如果未查到,返回None( U  F9 F* o; L! T2 q# ~
first_or_404()        返回查询的第一个结果,如果未查到,返回4045 R2 x7 O; L* {7 K
get()        返回指定主键对应的行,如不存在,返回None
5 U1 Y9 L) \( z  ]2 V; X. P% Nget_or_404()        返回指定主键对应的行,如不存在,返回404
. ?1 d+ V. c: i8 X9 W) U0 wcount()        返回查询结果的数量
5 R1 a4 g9 p+ G) k( J# s) n8 i9 Cpaginate()        返回一个Paginate对象,它包含指定范围内的结果
4 Q- g' l" _- k- q1.普通查询8 J1 L7 t! {' O9 U% b$ E  m
# 查询数据条数' I* e6 q" S/ X! @7 \
User.query.count()
- f+ w/ D  f# K2 }7 N- v9 A0 V" W5 K! |9 s+ O  @& M
# 查单条 获取不到none
' i. N6 W( @. I8 i+ quser = User.query.first()
$ ]6 O" Y* A! muser = User.query.filter(User.username=="小红").first()2 D) [0 l& K5 \4 Y
user = db.session.query(User).filter(User.username=="小红").first()2 R8 k+ A# ^2 U# k, T! w2 W
'''
( ?4 M( F2 p/ S2 D" I( q( mdb.session:是一种更明确的查询语法,适用于更复杂的查询场景,或者在不直接访问模型的情况下执行查询操作( y0 m" R- l5 D" R
'''
/ N* F& a+ p  V* O
5 q& I& w- I: P/ a6 m- V, U# 查所有
; s8 d9 i; x( `$ v/ xuser = User.query.all()  {: t1 p/ X/ R2 h
user = User.query.filter(User.username=="小红").all()# g) F2 v" i8 h9 p) c
user = db.session.query(User).filter(User.username=="小红").all()/ _6 c' t0 \+ \- b& t

+ T( Y0 S! I! i4 ?+ N' G# 只获取单条/ s  ^8 h; C4 R& k$ R
# 结果为一个时正常,多了就报错
. k1 j3 a# Q9 W% r2 [# one_or_none() 获取不到报错
; C5 u  d6 @( ]4 l* iuser=User.filter(User.username=='小红').one()  d% z8 Q* K4 h) x8 ?, D

: m5 @6 l& \' s# 获取不到报错, }* K7 d2 {# y1 ~* J4 K8 [" v
# get里面需要参数 是id
4 w; {, C' F7 `& euser = User.query.get(2)- x) h" @; `$ U

3 @3 ^! a3 o, x, ~2 }7 e3 p, x$ Q$ r2 R9 m1 ?2 L( z$ e
: K+ \+ h+ t6 A% G" O
2.条件查询. ^) J3 M. r4 `% N% A" P5 e! y' t+ U/ X2 [
# 条件查询
; H  @- u, K3 \$ x' n! o  user = User.query.filter(User.username=="小红",User.password=="123").first()
8 M- m% T! P& z' U& J8 K# 不等于3 O8 T2 E: ~( U5 ]) X
  user = User.query.filter(User.id!=2).all(). V" J  [6 v; K7 Y3 n/ H
# 大小于
9 R3 ^: V' w, r5 P0 S* _  user = User.query.filter(User.id>=2).all()
' A( h: A) P7 u  user = User.query.filter(User.id<=2).all()
" ^- J1 ^9 _4 _( @6 r2 G
' i- O5 X/ Q- k3 A9 ?% h#----------------------------------------, Y* o$ T- B% ~! h1 g; v
# 结尾为红5 K$ x5 H2 c# i4 S
User.query.filter(User.name.endswith("红")).all()
( d# {2 P: y% F  ZUser.query.filter(User.name.like("%红")).all()$ A/ U7 u! `  `" H  |* Z5 ~
# 开头为小
8 n) V( R- I. w& T5 C, XUser.query.filter(User.name.startswith("小")).all()
3 w3 V) d' f6 }5 C( M& KUser.query.filter(User.name.like("小%")).all()
+ ?6 a% V% W, a: F% T4 N8 b# 包含n mysql语法: ~2 D) s  j1 ~* ^" D6 A
User.query.filter(User.name.contains("n")).all()/ j# X  J; }" N9 Z) [2 Z$ m
User.query.filter(User.name.like("%n%")).all()  # 模糊查询
0 ]& o7 u; W) ~4 F7 v9 x
% u  m. I2 O% C0 k( U( W  J#-----------------------------------------0 W% U: s3 v$ y+ I. D
# 成员属于  in_
: Z6 w% K" r+ |3 C4 Y/ v. P. ?: w. BUser.query.filter(User.username.in_(['aaa','bbb']).all()
* H/ A# ~9 O. o9 _3 }9 i#成员不属于  notin_
0 e% `# C6 u6 t: x4 o5 z/ k3 TUser.query.filter(User.username.notin_(['aaa','bbb']).all()
6 T* ]  T9 T2 ~7 Y. o! I4 k; F3 x7 c( P3 W2 c; Z, s7 Y( z3 h2 M
#----------------------------------------
# p$ |5 i6 x9 K0 G  t, s  ^from sqlalchemy import and_, or_, not_
2 h, v& W2 Q- `! b" |! n# 和' I' A) f4 S/ H, c( U  \
User.query.filter(User.name.startswith('a'), User.email.startswith('q')).all()
- S3 h1 ?/ Q; f5 v9 g5 wUser.query.filter(and_(User.name.startswith('a'), User.email.startswith('q'))).all()
3 {, o2 n7 \; L. C$ D# j# 或者
% _! a) F6 {0 n- x+ j' WUser.filter(or_(User.username=='qaz',User.password=='qwe123')).all() / k- R, n4 c- V% r) Q  r
# 非
5 Z% c8 ?  i" V' f' o: yUser.filter(not_(User.username=='qaz',User.password=='qwe123')).all() , D( S7 B# X' i" F4 M, n: I
/ U. K* O$ D; B
#是否空判断" e/ ?& S0 K* i0 T" I
User.filter(User.username==None).all() )
9 g/ b* S" x' P8 {* |4 ^$ `2 Z8 JUser.filter(User.username.is_(None)).all() ), f4 B, ^+ [3 P) I
User.filter(User.username.isnot(None)).all() )( k9 d6 w5 @& I0 l) M$ F3 O

+ P6 J6 x0 Q, L- M) g3 [! r#------------------------------------------
8 g" i8 b6 E( C; g! f& a# limit 限制返回数据条数9 p7 b* s4 Q9 F+ N1 k' O3 {
# 开始条数是0) X- `4 E: H8 k% [$ h
User.filter(User.gender!=1).limit(2).all())
1 [, i# @- a, H# 从第几条开始获取 偏移
  \4 {0 z* K7 S7 M! iUser.query.offset(0).all(); O. G9 y( @; t* y' ~
# 从第2条数据到第3条 包前不报后' m- V3 E% ~, ]9 E
User.filter(User.username!='qq').slice(2,3).all())
# S7 E, }# e" v$ ]; |$ g$ z: n$ ~+ G; \: G  \( j3 {# l' Y
# 排序 order_by 默认正序& z0 g: ^. C$ F9 C; J
User.filter(User.username!='aa').order_by(User.username).all()
4 ^; i; f+ s( t- g User.filter(User.username!='aa').order_by(User.id.asc()).all() 正序
8 P' b$ e: U" i& I* U& y: e User.filter(User.username!='aa').order_by(User.id.desc()).all() 倒叙7 e4 _& a3 S3 d' U

0 L( @$ ]( W$ g4 B# 注意:上面的可以随意组合5 V2 M% S( ]6 r+ j- \
# 其余后续补充
. L7 Y* J( \. E9 m
, I7 e- r: I, G5 L9 W. p" O0 L, {3 b) L
3.filter和filter_by2 p: q; n% n$ h' g- b2 k% e
filter_by和filter都是过滤条件4 [5 V* R7 a/ D; P
filter_by 不支持比较运算符,只能用=1 t& @9 w/ H* u& s3 y, c+ b

- p# P6 g/ B9 e5 n; L, ^+ B! r2 t# 返回的都是对象# u" v* j2 ~4 M
rows1 = User.query.filter_by(username='小红').all(), y% z4 E1 G+ @2 n' N
rows2 = User.query..filter(User.username=='小红').all()
7 B! F( S. T7 @/ A0 ^% L
0 M( _1 Y: S! W5 X# rows3 返回的是User的username属性,不是对象( }7 U' E& p7 F2 W$ S
rows3 = db.session.query(User.username).filter(User.username=='小红').all()+ r, O! D' g1 ?, \2 \% @7 R
# 返回的是select语句
* B, D& |, B2 R& x- F9 Qrows4 = db.session.query(User.username).filter(User.username=='小红')
/ H* s. c8 O; d: F; P; e5 V' ~$ M' e1 r$ Q8 U2 Y2 s/ W

* R  |# Q; Y/ m, M' ~6.增加
, p/ h7 q6 P1 f) @* L# 单数据增加  
! E5 e2 M$ g! j) q& P6 \, J  user = User(username="张三",password ="123",email="123@qq.com")
7 ?$ E0 K. @7 [; t  db.session.add(user)
9 P& K1 z6 k/ |2 l  db.session.commit()
5 K3 B( C6 B# I: i9 {3 j# U
0 R6 d! K1 v: J4 L: v: r  i#-----------------------------------
  V' G& q' d4 C# 多数据增加
' z" v* s7 F. X- [: V  G$ t# 后面两种可能会有颜色警告
7 [4 e( ^8 `) N  @+ t1 {1 N方法一:使用字典列表一次性插入多条数据
4 i) n1 L$ L  k* T& @1 J  |, W@bl_user.route('/index')
1 l. `5 i' P. f: c8 sdef index():4 g* I& |' ~' t4 E; e1 s8 X/ a7 u
    data_list = [$ d: C  H# v8 n7 S2 Y+ c
        {'username': 'value1', 'password': 'value2'},
! L, E  I, N. v- P' F7 G3 g' [        {'username': 'value3', 'password': 'value4'},
6 M: M, Y3 F. g6 U1 c    ]
2 Z; p6 |+ i0 i  }0 R4 u$ d" l7 m    db.session.bulk_insert_mappings(User, data_list)+ U% P* U1 V2 j  a1 C
    # db.session.bulk_insert_mappings(模型, 数据)
8 b: ^$ ^2 T6 B4 {- t7 ?    db.session.commit()5 t. t0 n# p) d- h# s  T5 G5 ]
    return '增加成功'& f0 U* |% C: K3 C
+ ^* w+ n0 W9 ?4 V3 u& v) M
方法二:将多个对象一次性保存到数据库
3 i3 P8 a! d- @4 G. Z) x5 i0 G@bl_user.route('/index')4 |' r, t; X; X- m, G& i8 d2 {
def index():! @& E8 X$ ^3 _3 X. ?( |/ Z
    data_list = [
  P0 @( C6 G0 s" f* s9 |        User(username='value1', password='value2'),
' r+ M5 H0 ]* o) ~! }2 r        User(username='value3', password='value4'),! k; `, b4 A3 W6 \% d3 C& p5 }
    ]' t9 t9 G) l1 y
    db.session.bulk_save_objects(data_list). o4 p6 {$ h" M# ~& \
    db.session.commit()
" C: ?$ p# I& w9 \! B    return '增加成功'$ k( `- [$ x1 j4 [

; T. `& g$ _: [方法三:8 x9 h: h) n# j/ F' }& E- y# L
@bl_user.route('/index')9 I0 E( p* _/ b8 j! k$ I2 Z
   data_list = [0 {6 W, l$ I( L0 I( u
        {'username': 'value1', 'password': 'value2'}," @0 L) E) t, w' t" C2 ^: f, k
        {'username': 'value3', 'password': 'value4'},
8 n, a5 c# D" j" S" Q5 m    ]
8 M4 V8 H4 D; `% C; n
7 O2 ]3 H5 ^+ F* U    data_objects = [User(**data) for data in data_list]7 v8 ~! B0 x8 `2 `* E6 V
    db.session.add_all(data_objects)
' \, b+ }0 B1 ]9 @5 ^4 [2 y; O" I# V    db.session.commit()
1 h# A/ f; b; ]7 `6 j3 E$ w. B7 m    return '增加成功'
( c0 m% D) U5 y/ T2 n( e6 l: v
; T! B( o* n2 q, p3 E
5 ^9 p4 I% |7 U4 w# ?7.修改' I3 n/ g4 f2 R1 }4 @& N4 s
方法一:先查询后修改 可能会丢失数据
6 Q, U) N% Z% W8 i( h. L8 nuser = User.query.filter(User.username=="小红").first()
! x8 M5 ~; P( Q: g) ouser.email = "abc@163.com"0 H0 P$ h; Q+ q$ G. O$ f- z
db.session.commit()
( L; i/ t+ _2 E  E# I3 \
3 L7 H$ c4 u8 q6 _' d; |方法二:直接修改 推荐
0 b8 m- l% H6 G* Z6 C, R0 |8 yUser.query.filter(User.username == 'qqqq').update({'email': 'ABC@qq.com'})
/ ~2 h, B; z1 m. M) ]db.session.commit()5 W2 u$ N# ^! J& b
; B; ^4 t; T+ ?+ e1 y+ N! p: Q
#--------------------------% f0 L; N% e, |5 |+ k# b5 E
# 批量修改 列表套字典
) e0 O& R  _2 N# 注意必须要有id 确定修改那一条
6 ~$ E/ _) q' Y8 ]8 O3 C4 o' j    user = User.query.filter(User.id == 1).first()& M& _9 v2 D+ C3 @3 ^- ~; ]
    data = [{'id': user.id, 'username': 'zzzzz', 'password': '12345678'},; D( d0 G# @* w
            {'id': 2, 'username': 'aaa', 'password': 'zxcv'}]
; S! z$ M; z  a; v5 C    db.session.bulk_update_mappings(User, data)
% @2 v' E" P* {5 m- S/ h( r    db.session.commit()$ G9 v0 [8 y7 b% l- W8 p) e
; l: |. T3 T- K! A! F! J" u# {, K% P

* Q! @$ j# q; U8.删除
5 j: z. a+ u  ~方法一:先查询后删除 推荐
- q, [1 o2 w* G' ?% Quser = User.query.filter(User.username=="小红").first(); F) `% i! H$ R5 O, Q4 I; M
db.session.delete(user)& u2 t0 U* Z3 c
db.session.commit()
3 @, Y6 a7 L! ?5 x) B
9 C( W- n$ ?  W+ Z. x方法二:直接删除 可以删除多个
" X2 i2 W+ h5 b! o, kuser = User.query.filter(User.id == 2).delete()
* T5 M9 y4 c' ]db.session.commit()/ J% a, R# o* _3 C: B/ y
; X* n) t6 i& z9 m) P& m* G
# 假设有多个xxx 那么就可以把xxx全部删除: e& X3 ]& E$ r/ t. G& X
user = User.query.filter(User.username== "xxx").delete()# \0 _0 T1 j2 j0 R9 N$ Q
db.session.commit()
. C' D3 r% ?6 ^+ Ncv'}]
$ y9 W2 |: U1 o. e* X    db.session.bulk_update_mappings(User, data)
  S, `" Y2 f" ?& b& ?/ x    db.session.commit()
& U% _8 V6 c" w) N& [# r
6 a/ i2 O+ ^& s9 |/ z; @
" E. W/ E, [$ f+ H, J; Z8.删除+ ^) B' Z3 F; M9 ^
方法一:先查询后删除 推荐1 Q& |, I8 O( Y  e* t; k; P
user = User.query.filter(User.username=="小红").first()
3 p. w/ @! C; ^! pdb.session.delete(user)  e6 U! R' c3 J
db.session.commit()& q7 v- A, M+ v( X, y
3 [6 E4 f4 V: Y5 g6 f2 R
方法二:直接删除 可以删除多个
) M6 M" d$ z0 f5 Huser = User.query.filter(User.id == 2).delete()
% C2 I" m) f4 E$ @& Y) Pdb.session.commit(), B+ x; p% J) e2 {

% _  b8 r! N' K& ?# E# V4 j# 假设有多个xxx 那么就可以把xxx全部删除0 S2 L! M: S7 V1 x: s) e- x
user = User.query.filter(User.username== "xxx").delete()8 Z3 E& J1 ^; ~' O
db.session.commit()
4 X7 s$ U/ O2 e  W1 G; Y' r7 h- l! ~) \4 J

0 u% C  i1 p7 b4 [
 楼主| 发表于 2024-7-30 22:52:09 | 显示全部楼层
A Simple Example
# B2 p& `; H. L: m) e. qfrom flask import Flask* H5 [2 u& l, D* \* n
from flask_sqlalchemy import SQLAlchemy+ K- W2 W$ H3 ~5 M2 b! |  H
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
% V3 [. K. ?4 s5 o% k6 D6 X
2 ^6 }4 X! M$ ?) A' O9 Aapp = Flask(__name__)& s5 G; O, g* `$ {, M' F
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.sqlite"8 ]" @3 Y; b$ G
  V$ X  g4 R: G4 i
class Base(DeclarativeBase):
9 }- O0 }! K% H  ]  pass4 G9 _0 s* i* z6 c: P! y
5 R5 }8 R9 a& c$ \% l
db = SQLAlchemy(app, model_class=Base)  L' s$ u- l6 O
$ r0 `+ ?( Z( {
class User(db.Model):6 _5 X- T/ W, t: Q6 h. F
    id: Mapped[int] = mapped_column(db.Integer, primary_key=True)
0 X" s4 V; z2 m/ W- D    username: Mapped[str] = mapped_column(db.String, unique=True, nullable=False)
$ w' o' a3 ~6 C. H8 _' ^; A/ l$ A/ u) W9 \0 d% q* ?
with app.app_context():
6 Q7 W; Z8 y' [5 l    db.create_all()
( E. `4 e* T% D( {( x3 j3 |* @1 |$ J8 B' l' r) D2 d
    db.session.add(User(username="example"))
: b5 m6 [; j5 f& f    db.session.commit()
' `: U: h& k' Z' G3 [9 ?+ s+ O+ i. u5 C
    users = db.session.execute(db.select(User)).scalars()
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-8 21:23 , Processed in 0.056263 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

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