fastapi-sqlalchemy
sqlalchemy
sqlalchemy是python的orm工具,被整合进fastapi里面了
updatetime应该在model生成而不是 请求时生成,因为前端会给你传乱七八糟的,这个字段应该是对用户只读或者不可见的,应该在model里定义而不是pydantic里定义。
踩过的坑
懒加载
默认的sqlalchemy的session是懒加载的,有时候update数据不进去可以考虑这个原因,使用session.__repr__()
无感调用实现加载
密码编码
Engine Configuration — SQLAlchemy 1.4 Documentation
当密码中含有特殊字符比如@的时候,应该用特殊编码替换掉,其实python自带了一个包处理这个
import urllib.parse
urllib.parse.quote_plus("kx@jj5/g")
=>'kx%40jj5%2Fg' # @被替换成了%40,/替换成了%2F
Warning
Changed in version 1.4: Support for @
signs in hostnames and database names has been fixed. As a side effect of this fix, @
signs in passwords must be escaped.
在版本1.4中改变: 在主机名和数据库名中支持@符号已经修复。作为此修复的一个副作用,必须转义密码中的@符号。
update的时候报错
update方法默认为synchronize_session='evaluate'
在update
方法中,还有一个可选参数synchronize_session
,它用于指定何时将更改同步到数据库中。synchronize_session
有三种取值:False
、True
和'evaluate'
。
synchronize_session=False
表示不同步任何更改,而是只将更改应用于查询对象本身。这意味着查询结果可能不反映实际数据库中的更改,因为更改将在提交事务之前被回滚。这个选项通常用于性能优化,特别是在需要更新大量记录的情况下。synchronize_session='fetch'
表示立即同步更改到数据库中。查询结果将反映实际数据库中的更改。但是,这也可能导致脏读或死锁问题,因为其他并发事务可能正在访问被更新的记录。因此,这个选项通常用于更新少量记录或在并发性不是关键问题的情况下。synchronize_session='evaluate'
表示根据查询对象自动决定何时同步更改。是默认值。如果查询对象是一个普通的SELECT查询,则会使用True
;如果查询对象是一个JOIN查询,则会使用False
。
sqlalchemy.exc.InvalidRequestError: Synchronize session setting must be set to 'evaluate' or False for bulk operations
使用filter
方法进行筛选后,调用update
方法批量修改记录,SQLAlchemy无法确定何时将更改同步到数据库中,导致更新操作失败
update的时候synchronize_session=False
参数的诡异问题,忘了哪个错误了,直接设置为False就行了
插入json字汉字被unicode编码
插入json字段的时候,其中的汉字被编码为\u4f60\u597d
这样在数据库里和日志里都是unicode编码,但是查出来之后是正常的。
检查sqlalchemy的engine,pg的client db都是utf-8但是不知道为啥哪里还是latin1(我恨他)
[1]
select * from users;
alice|["𝓓𝓞Γ"]
bob|["\ud835\udcd3\ud835\udcde\u0393"]
在issue[2]里有人问了,最后官方加上了个参数[3] 在create_engine申请的时候加入参数指定json序列化器
engine = create_engine("mysql://scott:tiger@hostname/dbname",
encoding='utf8', echo=True,
json_serializer=lambda x: json.dumps(x, ensure_ascii=False))
之后存数据库就不会了
json字段的模糊查询
#todo pgsql的json字段模糊查询
session传递和生命周期
python根据函数实际参数的类型不同进行传递:
- 值传递:适用于实参类型为不可变类型(字符串、数字、元组)
- 引用(地址)传递:适用于实参类型为可变类型(列表,字典)
sqlalchemy 的session是引用传递,在函数中传递的时候,子函数查询完了,在外层中可以读出来。
查询出来的ORM对象本身在
Session
,在名为 identity map -维护每个对象唯一副本的数据结构,其中“唯一”表示“只有一个具有特定主键的对象”。 Session以无状态的形式开始。一旦发出查询或其他对象被持久化,它将从Engine
与Session
,然后在该连接上建立一个事务 .
也就是说在执行query之后的db对象维护的identity map不变,所以对这些对象还可以进行其他操作,但是此时如果query之后再update那么缓冲区就变成了update的结果,此时无法进行其他操作
session相当于每个query返回一个cur,多个query实际上是分离的
所以同一个query,应该先查出数据来再修改,但是取出来的数据会和db里面的不一致
Redis集成
#TODO Redis OM aioredis构建池,fastapi如何同步的建立redis连接池,普通使用如何建立连接池,怎样让redis链接随着app启动和关闭
小记一次FastAPI使用连接池调用Redis时,切换数据库的问题 - 一灰的随手记