You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Tortoise ORM 实现PostgreSQL字段写入时PGP加密的问题求助

Tortoise ORM 实现PostgreSQL字段写入时PGP加密的问题求助

大家好,我目前在使用Tortoise ORM配合PostgreSQL做字段的PGP加解密操作,解密功能已经正常跑通,但在创建/更新记录时的加密操作遇到了卡壳,想请教下有没有解决思路。


已正常工作的解密实现

我通过继承Function类实现了解密逻辑,代码如下:

class _Decrypt(Function):
    def __init__(self, term: Any, key, alias: str | None = None) -> None:
        super().__init__("pgp_sym_decrypt", term, key, alias=alias)

class Decrypt(Aggregate):
    database_func = _Decrypt

使用的时候通过annotate配合过滤,能正确生成SQL并执行:

await models.UserPhone.annotate(phone_decrypt=Decrypt("phone", key)).filter(phone_decrypt=phone)

对应的SQL日志是符合预期的:

DEBUG:tortoise.db_client:SELECT pgp_sym_decrypt("phone",$1) "phone_decrypt",1 FROM "users_phones" WHERE pgp_sym_decrypt("phone",$2)=$3 LIMIT $4: ['...', '...', '...', 1]

写入时加密的问题

但当我想在创建记录时加密字段值,仿照解密的写法实现Encrypt类时,却出了问题:

# 尝试的加密类,但无法正常工作
class Encrypt(Function):
    def __init__(self, term: Any, key, alias: str | None = None) -> None:
        super().__init__("pgp_sym_encrypt", term, key, alias=alias)

调用create方法时:

await models.UserPhone.create(phone=Encrypt(phone, key))

生成的SQL把Encrypt实例直接当成了字符串处理,完全没有解析成SQL函数:

DEBUG:tortoise.db_client:INSERT INTO "users_phones" ("id","phone") VALUES ($1,$2): ['id', "pgp_sym_encrypt('...','...')"]

随后Tortoise直接抛出操作异常:

tortoise.exceptions.OperationalError: invalid input for query argument $2: "pgp_sym_encrypt('...','... (a bytes-like object is required, not 'str')

我判断核心问题是:Tortoise在写入场景下,没有把Encrypt解析为SQL函数,而是直接把它当成普通字符串参数传入了。


我尝试过的无效方案

  1. 重写get_sql()方法:完全没被调用到;
  2. 重写__str__方法:虽然会被调用,但只是返回函数的字符串形式,还是没解决SQL解析的问题;
  3. 尝试function_cast():这个方法只在查询字段时生效,写入场景下根本不触发。

求助点

想请教下,怎么才能让Tortoise在创建/更新记录时,把自定义的Encrypt类正确解析为SQL函数执行,而不是当成普通字符串参数处理?感谢各位的指点!

火山引擎 最新活动