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

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2024-7-28 17:00:09 | 显示全部楼层 |阅读模式
1.介绍
2 Y+ a5 T/ Y0 K7 T2 }7 rflask用于orm操作表,一般使用flask- sqlalchemy 操作简单
8 `9 }, P3 D) e& S4 t4 B. f一般使用flask-sqlalchemy 2.5.1
! A/ O1 t7 }9 ^3 hhttps://flask-sqlalchemy.palletsprojects.com/en/2.x/; _" J0 Z- n( T' T* U- |3 L

" l0 ?  t& Z* J0 _! ?. i
+ ]' \. q- [+ i" S
. c4 P& m+ |+ o' r. d. {. i2.安装  p3 A* V0 N: i7 T  w4 v6 h
pip instal flask-sqlalchemy==2.5.15 R/ ~1 T: s6 r; ^0 {5 |
pip install Flask-Migrate==2.6.0  # 迁移数据库使用$ Z5 n+ R9 B6 d

$ s$ }; k# J' d# n0 y4 Y
9 d% C  ], }  S( x5 M) W3.数据库
& Y+ }# |/ i1 z+ ]' Z1 r1 |5 D1.配置 连接数据库; Z6 M  H/ K# p& E% E
代表驱动) G$ j+ b8 m: ]6 I& B) `) O8 V4 C
MySQL-Python  # 可以写mysqldb
2 y3 j. G) a& ?% j    mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>
  \( f" R7 r5 B& E" n" [6 r/ h. x! a  i& e* t
pymysql1 z& f0 w2 e0 V& a% Z" a* X
    mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]8 i/ n; u. w1 z7 N( A& g9 O6 ^+ h

& ~+ Q/ c# M" v5 q9 Q: r: |1 S- FMySQL-Connector8 }- F' l( q6 |
    mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname$ x) l: B. h6 R3 w# x4 ]
! a0 p" t8 j& ?! b
% Q$ B8 J: C* @. O( N& p% J

1 ]  A/ f4 w5 {0 [# g需要安装不同的扩展 注意mysqlclient的版本3 D- h; @! _1 X: P% {2 F
可以放到配置类里面( b/ v- m/ z+ n6 ^

2 G5 k: p# A. q4 f% ?' X方法一
1 x, E" R( j- Y7 V0 ?/ b7 d- R$ SSQLALCHEMY_DATABASE_URI = 'mysql://user:密码@localhost:3306/库名?charset=utf8mb4'/ P, J! ]/ i+ _& M* e: T0 d
, D' |, P+ a% C9 t9 r# r- g% N
方法二1 u' J  _7 m. t8 n+ l# q3 K4 _' }
DIALECT = 'mysql'
2 P1 L8 C: k' k6 X/ \# pDRIVER = 'pymysql'& d5 p2 x4 K8 M) u- z
USERNAME = 'root'. e9 K8 c7 E3 a' Q, m' t
PASSWORD = '****'! n9 A6 I8 {  c9 H' f& L
HOST = '127.0.0.1'
& Y% F" F. l/ U( e4 oPORT = '3306'" J4 W  s% T; Z/ ^
DATABASE = '数据库名'
: l$ g6 n. J  [1 W, e
' n0 s. u" q5 eSQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABASE)" k+ B$ R+ A7 k* U
( x7 ?: \7 Y  v' ]* Z3 H  q

8 d8 d4 r7 I4 u1 N% i2.连接数据库
6 t9 h4 b0 x2 ]1 K" M0 o# }9 f1 实例化SQLAlchemy对象  可放入其他文件
- Q  L2 h( c/ E9 U( |from flask_sqlalchemy import SQLAlchemy9 T* h: g4 l2 Q# `1 u3 b" [
db = SQLAlchemy()4 h# A8 o/ T, P% w* G
/ Y" r* G  R3 E+ o$ k: Z; H
2 注册db. ?& w% T: n7 k# J+ X- K, }0 D

* s! z( K" k$ f( o% E  F1 W# 初始化迁移数据库) h. J; l" u7 _% O& E
migrate = Migrate()& y2 S# i) A7 |0 p& l* F/ h  q  [

8 u* S3 V3 J& m' kdef create_app() -> Flask:
: k& ^: C  i" J* A( I' s  o    app = Flask(__name__)
, |. Z- V' ~3 x7 h# t4 M    app.config.from_object(Config)
; T) z: ~0 V4 H    # 绑定数据库
( m2 X, _2 n% M7 ~' g    db.init_app(app)
) l0 q# B& i, Z5 m5 c( I
  I% \# B0 X- m0 s    # 迁移数据库
& j) t% u3 _5 W3 A! Z    migrate.init_app(app, db)
' n! K- n- D' I! d    return app
; L8 _+ z, V% F
. o7 S! ^7 c3 q& Q7 a+ v
5 B+ X6 K* }; m$ S注意命令可能无法迁移, b% K2 S! H. L( k

* U$ Y  I+ K3 A, ?+ Q  M1. 命令行一直报    K, I  D; p' r& T
# 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.
" {+ P  q  s4 e7 t# a+ X0 z: z8 H
这是在虚拟环境没有配置, m! e! R0 G& u  P. l

, X- W5 U) [5 J$ N0 _% o使用 .env 文件 来设置数据* {% |3 h0 g/ O+ i' E
# 下载 插件0 o% [0 r) p% V) e/ @: j; x+ |
pip install python-dotenv' ~0 Q  T' N9 d1 E  {* Y9 y+ W

+ H: \4 ]' _5 ^9 F$ ~' ~# 创建app
# v2 B% b+ f% z* e" y8 T$ ydef create_app() -> Flask:
  W6 m1 d& U+ M! J3 n2 q! p. D/ w    app = Flask(__name__)7 X9 G  a& B2 ^) g# g( x& r. Y
    # 要在最开始加载 后面才能获取到7 q' l2 P/ W3 K* j8 b1 j
    load_dotenv(verbose=True)
. M9 w. F  g" X; m5 P4 K4 J& q* X4 q+ E( m
    # 注册配置文件 生成/测试
) J' f, C9 C; {$ F+ i    # env = str(os.environ.get("FLASK_ENV"))! ^. b) R8 Z/ O
    env = str(os.getenv("FLASK_ENV"))- N/ H- F% }: k; c- c+ @7 t
    app.config.from_object(getattr(conf, env))
" R8 ~+ ~" E" A- N3 k7 R- ~1 L4 o; y. z& C! J: I
    # 绑定数据库
4 c# f/ g$ |$ _6 Z: {. w    db.init_app(app)
0 g0 H3 t. d1 f0 P  H/ L) j0 w7 O! t- h* Z. k: _3 d
    # 迁移数据库0 B5 N% \* I* r+ K. W/ D
    migrate.init_app(app, db)& j+ \3 ?( D* K+ J) t4 x& y; A8 w
    return app
7 T+ v7 J4 U, ~; w$ y6 o/ U#-------------------------------------# l0 d2 G" L: k- R2 q( O5 w
# .env 文件: c& {# b/ H: Q: M2 K
  H5 H( w- W' {8 y# A- ?
FLASK_APP=main.py # 自己的启动文件 默认是app.py
8 ?4 }7 K$ }. I$ P* ^FLASK_ENV=development
! x# U2 H: [) F" |/ WFLASK_DEBUG=True
8 @. p: n! Y& a; U1 D9 h" }. z; S5 _% o0 E9 X: b6 g( P. I
& ?5 b) L, A9 N. u& ^
这样就可以输入命令了
. P+ z2 o9 `2 t5 I0 }2 I7 K) E
. Y" N" ?! C) N% r! r7 ]$ p: L报错误 either 'sqlalchemy_database_uri' or 'sqlalchemy_binds' must be set.4 m5 _8 L2 r; F" G" L: f
没有把模型放到 view文件里面 只想要把 模型导入就好了,可以不使用! R  h/ Z% T1 D
from user.model import User
- l) l3 g9 r4 N- X; B: F1 d" }: R$ Y) N2 |' M% Y) E5 \9 }
) P2 C. c6 O/ b* I
3 迁移数据库
: E! S  [8 _( A& [4 G- z# 初始化一个迁移脚本的环境,只需要执行一次。* p8 M5 a4 s/ F0 L( o' B
flask db init
$ ?* k. v) i2 F5 o% K9 w) C# 将模型生成迁移文件,只要模型更改了,就需要执行一遍这个命令
  y! W9 [4 R5 V  S$ Sflask db migrate -m'迁移数据库'
' r6 X- w( @; u+ U# 将迁移文件真正的映射到数据库中。每次运行了migrate命令后,就记得要运行这个命令。0 `% @  Z/ s5 w" S
flask db upgrade
7 D; x2 I" l5 a1 y* \9 K# `#-------------------------------------+ [* a% N8 Y! q7 ^
flask db heads 查看当前最新的迁移id8 W* m6 Y% @" s: o( A+ X/ i6 W
flask db stamp heads # 更新
  D3 w# [  ~* I& c5 ?4 H1 ^( x. Bflask db current  # 查看当前迁移id+ `2 |+ A7 r$ N/ b- {8 m) V1 d
python manage.py db history  #查看历史
8 V4 ~7 K% ?: V. F0 D- Q+ vpython manage.py db downgrade 652a55840d  #回退版本
- N- A! d& F' l1 C9 G  v( @2 U& t  R- B/ i3 Z, M$ J
# K4 Y7 u) x* L
4 数据库其他信息
; V* A. K% [4 ~# 查询时会显示原始SQL语句
+ c" Z4 a; w+ Q" f1 s. mSQLALCHEMY_ECHO = True4 s4 r8 w3 H+ w
# 动态追踪修改设置,如未设置只会提示警告
7 h" h- U5 c5 _( U) lSQLALCHEMY_TRACK_MODIFICATIONS = False; {) f9 n4 y+ s7 b
# 数据库连接池的大小
7 A+ K, i, X+ V) K6 A& d2 LSQLALCHEMY_POOL_SIZE = 10
4 a; @0 T% v3 c# 指定数据库连接池的超时时间
4 Y4 G( g% g7 B3 _: KSQLALCHEMY_POOL_TIMEOUT = 10
: x+ K0 U/ O0 K* ]; V+ h& W* c# 控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。
# [: A: y0 f% rSQLALCHEMY_MAX_OVERFLOW = 2
4 n6 k* A* L3 K' E5 V! i0 a2 b! m  d# N8 E1 q

  t1 h5 v0 N  o  N名字        备注
: {2 o% X2 N- }" {# {SQLALCHEMY_DATABASE_URI        用于连接的数据库 URI 。‘mysql+pymysql://root:密码@localhost:3306/库名?charset=utf8mb4’
$ o$ A  H7 v( E2 Q* j/ y, H9 OSQLALCHEMY_BINDS        一个映射 binds 到连接 URI 的字典。更多 binds 的信息见用 Binds 操作多个数据库。) U0 Z) ]( u5 _' W; r3 I' r
SQLALCHEMY_ECHO        如果设置为Ture, SQLAlchemy 会记录所有 发给 stderr 的语句,这对调试有用。(打印sql语句)$ A7 `# ?! p6 d- t( r
SQLALCHEMY_RECORD_QUERIES        可以用于显式地禁用或启用查询记录。查询记录 在调试或测试模式自动启用。更多信息见get_debug_queries()。
( F  z: l: _, p* rSQLALCHEMY_NATIVE_UNICODE        可以用于显式禁用原生 unicode 支持。当使用 不合适的指定无编码的数据库默认值时,这对于 一些数据库适配器是必须的(比如 Ubuntu 上 某些版本的 PostgreSQL )。
6 b. t+ Q$ c# \' M6 ~SQLALCHEMY_POOL_SIZE        数据库连接池的大小。默认是引擎默认值(通常 是 5 )9 h4 s: h8 {) S/ d, N, h
SQLALCHEMY_POOL_TIMEOUT        设定连接池的连接超时时间。默认是 10 。
  T/ ?0 v/ M. U  w0 WSQLALCHEMY_POOL_RECYCLE        多少秒后自动回收连接。这对 MySQL 是必要的, 它默认移除闲置多于 8 小时的连接。注意如果 使用了 MySQL , Flask-SQLALchemy 自动设定 这个值为 2 小时。3 ?1 e6 P6 t; l+ X1 y9 ~: p; c
4 创建表
8 @* M9 M+ B5 E4 Dfrom core import db        #这里需要引入实例化的SQLAlchemy对象& m8 v; ^$ B5 q

. `( p  O4 q9 z: Jclass User(db.Model):* C( A' ], M) q6 |% E0 H" p
    """用户表"""1 r  A' G7 t! v, q& ^
    __tablename__ = 'user'  # 创建后表名 小写
$ ]2 {, D: q' A! l4 C    # __abstract__ = True  # 抽象表 不创建这个表 可以继承1 L9 J# a5 x5 S7 j$ R9 O
* B7 W, n" W' w* f" S0 a- t2 L
    id = db.Column(db.Integer, primary_key=True, comment='id主键') # 必须要有
( `7 h4 b0 K( Y3 f2 n    username = db.Column(db.String(32), unique=True, comment='用户名')
  H. c* I1 A' j3 B7 a4 l    password = db.Column(db.String(64), nullable=False, comment='密码')3 Z0 H' f, m" Z/ o  o
    gender = db.Column(db.Boolean, default=0, comment='0 男 1 女')9 c7 B5 c) \( ~* n, w7 y. ?
    avatar = db.Column(db.String(125), default='http://s5p.hd-bkt.clouddn.com/default.jpg', comment='头像')* z( f2 F. @) E- H7 }7 Y
    addr = db.Column(db.String(256), comment='地址')
- p' P! Y4 [3 p% G    email = db.Column(db.String(125), comment='邮箱')
' N9 ]& _8 [2 t    mobile = db.Column(db.String(11), comment='电话')
1 P) i% r$ q+ N; q4 }( I- v6 L    login_type = db.Column(db.Integer, comment='1 电话 2 邮箱 3 用户名')
, R) A( I9 H3 E& T$ \8 t7 b
6 \& [7 F" U. \& A    def __repr__(self): # 查询的返回 和str一样! l. c" d. L2 C1 T* H0 J
        return f'<{self.__class__.__name__} {self.username}>'
  G& e; p8 w& R/ Y) Y% y* X' O6 f% }6 E

/ ~3 j6 ?5 }2 K0 I1.字段解析3 y' Z" ?4 J1 s8 ^, e- A
类型名        python中类型        说明
5 I0 z8 ~. [" {$ W0 l$ O5 LInteger        int        普通整数,一般是32位
+ i- ~, U  z' F) o. o6 s$ _SmallInteger        int        取值范围小的整数,一般是16位( M) W' k7 T/ r+ F1 J+ Y
BigInteger        int或long        不限制精度的整数2 `# `% i2 R! V. N- U% Q) H6 [
Float        float        浮点数
* t8 `- ]( P$ x# yNumeric        decimal.Decimal        普通整数,一般是32位
0 P0 a3 x& e6 P9 V- q7 `0 fString        str        变长字符串
/ y" [+ g. K+ P  hText        str        变长字符串,对较长或不限长度的字符串做了优化
% v; W- P8 N6 u6 D* u! UUnicode        unicode        变长Unicode字符串
3 j( N" W! P3 k/ qUnicodeText        unicode        变长Unicode字符串,对较长或不限长度的字符串做了优化
% l7 H$ h0 {7 U4 L, r( N* [Boolean        bool        布尔值0 m  {5 P8 e, Y; ?2 W2 D; P
Date/DateTime        datetime.date        时间2 A( W+ i2 R% T+ C+ d
Time        datetime.datetime        日期和时间
; G6 ?: m( A0 O, y( H: w- yLargeBinary        str        二进制文件
5 A0 c" X# P) o! C6 P8 V0 D2.表属性) h$ D  Y" z! R' `* @1 n
选项名        说明, N, h2 D9 h& m4 ]6 o' p! t
primary_key        如果为True,代表表的主键
+ Q2 d% K2 H6 y- |unique        如果为True,代表这列不允许出现重复的值
% J6 b% n" d/ windex        如果为True,为这列创建索引,提高查询效率- I6 ~0 K' ^) C' o) q/ E
nullable        如果为True,允许有空值,如果为False,不允许有空值$ x  y$ e) v) R. t: d7 E* ~
default        为这列定义默认值, }& S0 Y7 R) I/ w4 M$ B
5.查询
  D7 ^& c  w' u. H1 ]3 H2 g注意只要对数据库操作就需要 db.session.commit()
. a' j9 c7 g. S, l1 I) k# H( S2 P( G& H3 X
查询方法
0 y/ ~1 l4 B, I2 n方法        说明, G8 s1 t' e7 Y# v$ i) O9 R6 O' G: ^
all()        以列表形式返回查询的所有结果. J2 ^: u3 N  q0 b
first()        返回查询的第一个结果,如果未查到,返回None7 f! c7 D! v! }+ E2 {9 [  N) w
first_or_404()        返回查询的第一个结果,如果未查到,返回404
7 W# y  |7 x9 q9 qget()        返回指定主键对应的行,如不存在,返回None9 I! `+ m  `5 L7 E
get_or_404()        返回指定主键对应的行,如不存在,返回404
0 b+ b# u7 C: g! p4 Q3 ^count()        返回查询结果的数量
7 P, i  w0 q4 k8 q$ L! ppaginate()        返回一个Paginate对象,它包含指定范围内的结果& j3 n" R! u/ P
1.普通查询
( t1 t. B& [4 z# 查询数据条数7 D7 L! S% f  H% r2 H
User.query.count()6 [! r3 s9 ~) [

+ M3 x4 y+ j1 M' ?* }% o# 查单条 获取不到none0 B" c  d! M0 |* a$ |/ D- ?2 y
user = User.query.first()$ o3 y" w# z: _; o# R2 Q% b4 v! g% C9 ]
user = User.query.filter(User.username=="小红").first()/ S! A3 w$ X- I6 B% q+ Y7 b
user = db.session.query(User).filter(User.username=="小红").first()- c; ~/ h0 \' n9 J& M% t
'''7 U" o5 @5 Z6 A: G9 a8 O) B  g
db.session:是一种更明确的查询语法,适用于更复杂的查询场景,或者在不直接访问模型的情况下执行查询操作
1 E4 S* i; T/ N  Z5 B( P'''
$ N8 I0 I) B! ~  D4 |! c- G" O7 N( T7 y! C- S' j% {6 j  z% E3 ^9 I- @
# 查所有- v, O6 d6 t9 ?$ F' n" U4 Z8 |
user = User.query.all()
, I- S# K$ Z( o0 O+ O1 {) Duser = User.query.filter(User.username=="小红").all()
; w: M( m" P! ^6 G' P: U0 guser = db.session.query(User).filter(User.username=="小红").all()6 k" f; M, V8 |' k

+ S, P5 N$ q6 d# 只获取单条
7 K, h" g/ z1 d3 ^- M) [* E( Z# 结果为一个时正常,多了就报错" ~  c. k, P0 B- Z- L+ I' i
# one_or_none() 获取不到报错0 |! k9 t9 R' m0 D* \/ X
user=User.filter(User.username=='小红').one()
7 [+ Q, f# \0 @8 }' Y: ^
' S* Y) W+ n; d& d4 N: B$ I$ D) m9 z# 获取不到报错
' q. V; P/ T3 d7 ^* H  l# get里面需要参数 是id. u; X. A2 C% d: M9 L9 ~
user = User.query.get(2)
( U2 ]$ `% f# ^% Y' H/ P  k* q4 F$ l: ^" E- G

* f& {6 r& j& N1 q
7 p- f! F* y' P6 U' H$ K7 f2.条件查询0 F% v. _, u9 Q
# 条件查询8 s/ C( I4 B# @
  user = User.query.filter(User.username=="小红",User.password=="123").first()
; ~+ `% c0 ^) I7 n. d# 不等于
- |' H* s9 O  M0 g  user = User.query.filter(User.id!=2).all()
* s" C" F# ^/ Q  ?! e+ P/ Y1 ^# 大小于
7 _7 X- S9 v# f$ _6 n, T! k- y  user = User.query.filter(User.id>=2).all()
6 Y" Z! ~: E7 M' Y" q3 R  user = User.query.filter(User.id<=2).all()/ ^: t! O9 t; h
6 {2 L& M' h  ~) J
#----------------------------------------
' X/ D8 E6 r( x4 _# 结尾为红
( v1 x; I  ?& {4 U# iUser.query.filter(User.name.endswith("红")).all()2 r2 z! Y! \; Z9 M6 L( U/ y
User.query.filter(User.name.like("%红")).all()! f+ [. i- [0 V  U) R
# 开头为小
1 D+ W& S/ `; K& a; Y0 N1 AUser.query.filter(User.name.startswith("小")).all()
8 V; o+ w' X. T+ eUser.query.filter(User.name.like("小%")).all()* b; B: {7 i: J. k8 j: R
# 包含n mysql语法
: u' V- {1 x8 P: O1 v% ~& w! dUser.query.filter(User.name.contains("n")).all()% z. n0 Q( f, z5 N& T) J
User.query.filter(User.name.like("%n%")).all()  # 模糊查询
) k# ?  }4 K$ N7 {+ [6 L- j/ y" k% }" u6 R$ R3 z$ ~; P
#-----------------------------------------' h0 W" n; c; v) d
# 成员属于  in_( C$ m' @4 N$ q5 {
User.query.filter(User.username.in_(['aaa','bbb']).all()
) L1 ?4 r* L- q5 H#成员不属于  notin_
. }) \' l2 q3 f# H+ T3 tUser.query.filter(User.username.notin_(['aaa','bbb']).all()
2 T8 Q$ x) U- b# d
/ M, C: O9 U7 y: M' y7 n3 k. S3 p#----------------------------------------5 d) k) O! z: _* L  G
from sqlalchemy import and_, or_, not_9 k# V& W' L1 r
# 和
5 F3 E, U/ e& U2 mUser.query.filter(User.name.startswith('a'), User.email.startswith('q')).all()/ O& T) G- Z( k  E$ R
User.query.filter(and_(User.name.startswith('a'), User.email.startswith('q'))).all()
; T4 q# O% w' G1 M# 或者
( M, Y4 `8 L- l# d8 F! VUser.filter(or_(User.username=='qaz',User.password=='qwe123')).all() ; H& j7 v& K" S* i( q
# 非- A% P0 N& R  a* m+ b" T( u! z; M2 L
User.filter(not_(User.username=='qaz',User.password=='qwe123')).all() . n# y) F$ K  K$ W! t) I( {+ W
5 h8 `$ K: A6 t4 i% W  e
#是否空判断
; R7 l$ R' E7 r$ V& C2 v, L" WUser.filter(User.username==None).all() )
; G0 }# w, p7 X- X  fUser.filter(User.username.is_(None)).all() )$ T5 z: |5 q) ?7 L. }; d
User.filter(User.username.isnot(None)).all() )
& J4 l/ [$ l- a  c4 T( l' z
; {+ f& i6 t, F, l#------------------------------------------, {& e+ Q9 c/ B7 c! _2 c, m
# limit 限制返回数据条数
* S5 u" |9 t2 x2 U# 开始条数是0
4 m9 R- O) P! m; B6 q5 XUser.filter(User.gender!=1).limit(2).all()): B! p( n- F) J7 \. u
# 从第几条开始获取 偏移
! e' C. z9 Q) i$ F2 R: {. XUser.query.offset(0).all()
. q7 ]$ b2 [  y, W% i# 从第2条数据到第3条 包前不报后- P8 j' o2 }5 y8 K3 Y: m' o$ \
User.filter(User.username!='qq').slice(2,3).all())" ^1 u- X3 c4 o7 F8 o, Z- f; }

; G( E% v4 O1 b8 V4 G4 F1 `3 X. q( ]# 排序 order_by 默认正序/ d7 ]; P  n, b$ `2 {; M. e& A7 j# x! q" t
User.filter(User.username!='aa').order_by(User.username).all()
, q' }2 i3 F) t7 T+ s: a- G User.filter(User.username!='aa').order_by(User.id.asc()).all() 正序
/ e# V9 T$ e1 F; o: T6 X User.filter(User.username!='aa').order_by(User.id.desc()).all() 倒叙) e" Q0 w% K$ t9 }

  h( q+ M/ q6 P# 注意:上面的可以随意组合1 G. z/ O& ?  u+ u7 D
# 其余后续补充' V3 i% a. g& d! [/ ^
5 k$ F" E0 c6 W. ]
9 m/ f4 K4 f9 c- @5 D* x' d
3.filter和filter_by1 {; b3 ?: }3 W
filter_by和filter都是过滤条件" Y/ ]$ T. v, L1 E2 C- L! g) l
filter_by 不支持比较运算符,只能用=2 _0 L6 f- o- e7 P! i
$ H! M' {% P3 K/ `+ E
# 返回的都是对象) J: h0 U; V$ n: j1 N+ K
rows1 = User.query.filter_by(username='小红').all()5 M5 q$ ]5 ?1 m, M* Y
rows2 = User.query..filter(User.username=='小红').all()
0 s5 t4 v7 s8 i, i$ m
7 d$ ~! I2 j3 t& Y# u" K1 Q# rows3 返回的是User的username属性,不是对象$ S. k0 a3 D7 R, ^0 a2 x$ n
rows3 = db.session.query(User.username).filter(User.username=='小红').all()$ g7 ^5 Q0 }8 p9 e" K
# 返回的是select语句
7 m6 Q+ q. n: }. U4 Grows4 = db.session.query(User.username).filter(User.username=='小红')
' f! m+ a  }3 f" `2 k% ], c, C* L% y) Y" Q4 S

( U) h7 D6 P( `2 O6.增加. G" l. ~* z6 N/ b9 t2 P
# 单数据增加  2 p& t# m; K4 {- N
  user = User(username="张三",password ="123",email="123@qq.com")
  ?' `# h" o9 R! U2 Q2 ~+ J  db.session.add(user)$ N1 P) d2 q% e7 ^- s  a* e- u
  db.session.commit()/ P' f0 o! @0 K1 l

* g/ d$ W4 r- o+ h, |/ H; Q#-----------------------------------
# D6 X3 }; E5 b3 Z) a/ T& \# 多数据增加
( @) k3 M0 A- e# 后面两种可能会有颜色警告
& h- T) K) F/ T, G! |# h  W方法一:使用字典列表一次性插入多条数据  B# X' `9 n6 P$ Q
@bl_user.route('/index')
0 C! i! d! M4 j5 t! N/ K( Kdef index():
4 u, v$ T9 Y4 W2 i# z$ i  Z* m    data_list = [
9 n) Z+ x( A- O% p6 H' {        {'username': 'value1', 'password': 'value2'},
8 i9 |) z3 p( O* s0 n        {'username': 'value3', 'password': 'value4'},
) J0 t0 Y2 z: @9 s    ]6 l7 w3 }8 R9 o. o0 \. M
    db.session.bulk_insert_mappings(User, data_list)
- b  X( c* {2 p    # db.session.bulk_insert_mappings(模型, 数据)
/ ^( v3 @% W5 m. f. h2 v; p; m    db.session.commit()
* {! X# t5 [8 d3 I) d. {6 r    return '增加成功') \  F" y+ q2 x. g  C

6 C) ?3 U% u: A, l$ O; I! z方法二:将多个对象一次性保存到数据库
; t2 r4 J4 c0 V( z+ K, p: g7 _@bl_user.route('/index')6 u' g, ~/ F/ ]$ m# B7 \
def index():
5 X4 r9 A8 Z8 {: a* [    data_list = [3 ~- V, |# H. ?' ?3 |/ z
        User(username='value1', password='value2'),
7 J; H7 T4 O/ j" q2 _. Z        User(username='value3', password='value4'),
- }2 T8 J' B5 r4 V* ]    ]+ m2 r- l1 n  y! c  z
    db.session.bulk_save_objects(data_list)
/ _9 r/ w6 o/ `7 r: X, H0 p    db.session.commit()
0 P  f$ h4 M! j$ d; `9 J    return '增加成功'
1 U  C3 c6 m9 g& F0 g* X1 ~4 F8 l2 ^# d9 j2 P5 H
方法三:2 d9 x0 ]# B- r) U
@bl_user.route('/index')
+ O- q! h3 D1 |6 l   data_list = [
8 x6 n+ k+ D1 H        {'username': 'value1', 'password': 'value2'},
1 J* |; i) ]5 E  I3 }$ Z$ Y' G6 x        {'username': 'value3', 'password': 'value4'},! f! t3 L. ~9 s" x- Y
    ]
( w5 ^( w+ K8 w0 x- Z
7 Z1 o2 c+ V; b3 U    data_objects = [User(**data) for data in data_list]
0 W1 y- v; n6 l! f/ w$ b' X1 B' {    db.session.add_all(data_objects)
9 _0 G; q! ?. C( U5 D2 f    db.session.commit()
. a  l' D" M0 D: D    return '增加成功'
! R2 b( @( y/ M4 j
7 x' }" e2 K1 I: a1 C6 e0 I  l. ~2 W1 o% \
7.修改
3 `5 ]# X& J, u4 ]" x方法一:先查询后修改 可能会丢失数据) K: z7 F# H9 V9 N+ m4 r7 ^9 I
user = User.query.filter(User.username=="小红").first()
  h/ U, f" k* }' p- y( _) Ouser.email = "abc@163.com"
$ I* @& X! E! y# l) w# ldb.session.commit()
5 s& n: W. T" `2 q: E8 W' T, ]! B% Y+ R6 b& r# {
方法二:直接修改 推荐. N( e) E% }: m
User.query.filter(User.username == 'qqqq').update({'email': 'ABC@qq.com'})
0 r5 v$ \2 j. R1 \6 zdb.session.commit(), V3 D$ E/ k, L4 g4 `8 D9 f

) s' K5 w+ n: I% ?#--------------------------( R4 W4 s! M& f- R
# 批量修改 列表套字典$ A. B7 m7 y, R8 K: U4 M) ?! V# x- T
# 注意必须要有id 确定修改那一条
" M' e! m# Z  _4 X7 T    user = User.query.filter(User.id == 1).first()
% j* U7 R4 ^0 {: m2 R, @% G" N  k    data = [{'id': user.id, 'username': 'zzzzz', 'password': '12345678'},6 \& m+ l) K2 J0 [- `
            {'id': 2, 'username': 'aaa', 'password': 'zxcv'}]9 w; `" z  H* J/ T
    db.session.bulk_update_mappings(User, data)
  R# L" O2 y/ o4 q  D4 v; H& s    db.session.commit()
  e: B9 T( ^! r* o: |4 \% _
9 A9 M7 ?/ ]0 c; \, {/ K4 [: @/ @6 w$ x' O& {( g5 ^; t
8.删除
% F/ E( Z) P1 o9 @方法一:先查询后删除 推荐6 ]$ w3 s) e! v
user = User.query.filter(User.username=="小红").first()
  B6 m$ P, X( G; B. y9 p' Mdb.session.delete(user)" {: E- p, h2 R& l, n$ }  q
db.session.commit()2 [3 R" |8 b. [1 c) j

- W: I" K+ n9 _+ W+ I! y方法二:直接删除 可以删除多个
. O$ W$ [9 M) R' x! [7 Z/ ?4 v! [user = User.query.filter(User.id == 2).delete()
) |$ x6 {5 {  r! B# K2 H4 s0 V* Adb.session.commit()
9 }; G& s7 A( U* A* T& x: i0 ?5 c8 v) x( @6 p
# 假设有多个xxx 那么就可以把xxx全部删除3 I. ^8 I7 Z! |9 u4 e9 K2 Z
user = User.query.filter(User.username== "xxx").delete()  ]. Y! l2 j$ m  R* P( J0 |
db.session.commit(); _# |: E; d7 \' r1 V' v3 {: [
cv'}]2 e, P7 d! d5 U8 {, o: [
    db.session.bulk_update_mappings(User, data)! s5 V" H5 _3 x
    db.session.commit()
! r6 P6 g9 F% c' O+ m9 G5 v- I/ E! S  E  b, r0 I

1 T9 u, }0 m1 ?$ U( e. `% ^$ p1 Y8.删除
( X* I, }6 d" G方法一:先查询后删除 推荐% B( j7 p- j; b7 f! z( ?; B, ^
user = User.query.filter(User.username=="小红").first()
. J+ O6 F# L4 I, f( ^9 \! D$ Zdb.session.delete(user)" k* z" W4 n. Q+ I: ?6 m
db.session.commit()
% U% |$ E* o! `7 o9 b
4 E1 h+ R5 c& D. n3 k3 T9 S9 j9 R: ?方法二:直接删除 可以删除多个
# e3 W5 W6 T3 t4 buser = User.query.filter(User.id == 2).delete()) D. D/ H% @* `
db.session.commit()8 @) p% |/ A5 Z+ P

6 D+ N" c  l' H# 假设有多个xxx 那么就可以把xxx全部删除
- ^: F, Q) g$ I+ F6 D# r5 Tuser = User.query.filter(User.username== "xxx").delete()) _2 I! ?2 z, _4 T) v
db.session.commit()
& o8 A  @$ H0 B4 Y/ J! T% O
: ^) o5 o/ c6 q5 @+ f) G
4 @. K! R' ~5 B5 _

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2024-7-30 22:52:09 | 显示全部楼层
A Simple Example
! N& r. }$ o! u  g9 @5 B4 s! rfrom flask import Flask
4 z2 _7 S; q/ efrom flask_sqlalchemy import SQLAlchemy' q5 Z9 U" R/ g  g3 s. i+ t
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
0 R! P7 `( t8 H( W
9 b$ s5 c" j  M. N& japp = Flask(__name__). F1 O( Z2 m% S4 a# t* d8 M" a
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///example.sqlite"# m: Y6 ]& C% a8 i& g9 r1 }7 v( ~
8 i# ^  r; T! ^1 R6 r* n  S* B
class Base(DeclarativeBase):
3 Y5 t3 v2 U; K' {- B; F  pass3 X# ]9 N5 b. `, b- r- F2 l' `3 }/ H
6 m+ t9 h0 k6 ^# Z
db = SQLAlchemy(app, model_class=Base)6 W+ _: D9 Y& U. X6 s

5 V& \+ z* c/ R0 F; |$ B) E! ~1 Mclass User(db.Model):/ x, N7 }1 ?2 y% s2 y3 L( a
    id: Mapped[int] = mapped_column(db.Integer, primary_key=True)3 ^, Q/ D& K* k9 ]+ ~
    username: Mapped[str] = mapped_column(db.String, unique=True, nullable=False)
0 z4 e2 R0 j& O) s
, u- X! y4 a2 @0 W3 ewith app.app_context():$ [6 V6 P: E) T! @- U- j
    db.create_all()
( }* o% E( a1 d6 J* f, E3 Z' P8 s1 q: |" D5 {# r
    db.session.add(User(username="example"))0 l# H7 j1 s! [: E0 f
    db.session.commit()" z( ^2 l6 Q: z7 q$ Y* m) K

# U8 R9 U2 y! x    users = db.session.execute(db.select(User)).scalars()
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 00:31 , Processed in 0.018459 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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