无法在 SQLAlchemy ORM 中使用占位符“%s”(格式:AUTO)调整类型“dict”

问题描述 投票:0回答:1

我想检查特定的电子邮件模板是否在任何其他模型实例和模型规则中使用,我们在运行下面的查询时有操作(JSONB),但出现错误

我添加了示例查询和错误响应

操作栏响应结构示例

{
   "negative": [],
   "positive": [
     {
       "action": 45,
       "email_template_id": 1
     }
   ]
}


查询查看email_template

event_exists_subquery = exists().where(Event.email_template_id == EmailTemplate.id)

subquery = exists().where(
    or_(
        func.jsonb_contains(
            Rule.actions["positive"],
            func.jsonb(literal({"email_template_id": EmailTemplate.id})),
        ),
        func.jsonb_contains(
            Rule.actions["negative"],
            func.jsonb(literal({"email_template_id": EmailTemplate.id})),
        ),
    )
)

statement = select(
    EmailTemplate.id,
    EmailTemplate.name,
    case((or_(event_exists_subquery, subquery), False), else_=True).label("is_used"),
)
email_templates = (await request.state.db.execute(statement)).mappings().all()


错误响应示例

sqlalchemy.exc.ProgrammingError: (psycopg.ProgrammingError) cannot adapt type 'dict' using placeholder '%s' (format: AUTO)
[SQL: SELECT email_templates.id, email_templates.name, CASE WHEN (EXISTS (SELECT * 
FROM events 
WHERE events.email_template_id = email_templates.id)) THEN %(param_1)s ELSE %(param_2)s END AS is_editable, CASE WHEN (EXISTS (SELECT * 
FROM rules 
WHERE jsonb_contains((rules.actions -> %(actions_1)s::TEXT), jsonb(%(param_3)s)) OR jsonb_contains((rules.actions -> %(actions_2)s::TEXT), jsonb(%(param_4)s)))) THEN %(param_5)s ELSE %(param_6)s END AS is_used 
FROM email_templates 
WHERE email_templates.deleted_at IS NULL]
[parameters: {'param_1': False, 'param_2': True, 'actions_1': 'positive', 'param_3': {'email_template_id': <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x115d52ca0>}, 'actions_2': 'negative', 'param_4': {'email_template_id': <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x115d52ca0>}, 'param_5': False, 'param_6': True}]

我有以下包裹:

  • python =“^3.11”
  • fastapi =“^0.111.0”
  • sqlalchemy =“^2.0.28”
  • psycopg =“^3.2.1”
  • psycopg-二进制=“^3.2.1”

数据库:Postgres


我也尝试了以下方法来解决相同但出现相同类型的错误

subquery = exists().where(
                or_(
                    Rule.actions["positive"].contains(
                        [{"email_template_id": email_template_id}]
                    ),
                    Rule.actions["negative"].contains(
                        [{"email_template_id": email_template_id}]
                    ),
                )
            )
python sqlalchemy orm subquery fastapi
1个回答
0
投票

您可以让 Postgres 使用

jsonb_build_object
函数来完成此操作,而不是尝试在 SQLAlchemy 中构建 JSON 文字,其工作原理如下:

so# select jsonb_build_object('a', 1, 'b', 2);
 jsonb_build_object 
════════════════════
 {"a": 1, "b": 2}

在您的代码中,您的条件可能如下所示:

import sqlalchemy as sa
...
subquery = sa.exists().where(
    sa.or_(
        sa.func.jsonb_contains(
            Rule.actions["positive"],
            sa.func.jsonb_build_object("email_template_id", EmailTemplate.id),
        ),
        sa.func.jsonb_contains(
            Rule.actions["negative"],
            sa.func.jsonb_build_object("email_template_id", EmailTemplate.id),
        ),
    )
)
© www.soinside.com 2019 - 2024. All rights reserved.