【问题标题】:How to use SQLAlchemy TypeDecorators to compile raw SQL如何使用 SQLAlchemy TypeDecorators 编译原始 SQL
【发布时间】:2021-05-27 00:35:00
【问题描述】:

我有一个使用 uuid.UUID 的 SqlAlchemy 查询对象:

import uuid
import sqlalchemy

foreign_uuid = '822965bb-c67e-47ee-ad12-a3b060ef79ae'
qry = Query(MyModel).filter(MyOtherModel.uuid == uuid.UUID(foreign_uuid))

现在我想从 SQLAlchemy 获取原始的 postgresql:

qry.statement.compile(dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}))

这给出了以下错误:NotImplementedError: Don't know how to literal-quote value UUID('822965bb-c67e-47ee-ad12-a3b060ef79ae')

这似乎是因为 SqlAlchemy 只知道如何处理基本类型。 The documentation suggests 使用 TypeDecorator 甚至为 GUID 提供一个:

from sqlalchemy.dialects.postgresql import UUID
import uuid

class GUID(TypeDecorator):
    """Platform-independent GUID type.

    Uses PostgreSQL's UUID type, otherwise uses
    CHAR(32), storing as stringified hex values.

    """
    impl = CHAR

    def load_dialect_impl(self, dialect):
        if dialect.name == 'postgresql':
            return dialect.type_descriptor(UUID())
        else:
            return dialect.type_descriptor(CHAR(32))

    def process_bind_param(self, value, dialect):
        if value is None:
            return value
        elif dialect.name == 'postgresql':
            return str(value)
        else:
            if not isinstance(value, uuid.UUID):
                return "%.32x" % uuid.UUID(value).int
            else:
                # hexstring
                return "%.32x" % value.int

    def process_result_value(self, value, dialect):
        if value is None:
            return value
        else:
            if not isinstance(value, uuid.UUID):
                value = uuid.UUID(value)
            return value

但是它没有说明如何使用这个TypeDecorator。我需要在我的模型中以某种方式引用它吗?我是否以某种方式使其可用于.statement.compile 呼叫?

【问题讨论】:

  • Do I need to reference it somehow in my model? 是的。它将用作您的列Column('uuid', GUID) 的类型。另一种选择是跳过uuid.UUID 实例化并将foreign_uuid 字符串直接传递给CHARqry = Query(MyModel).filter(MyOtherModel.uuid == foreign_uuid) - 如果您真的不需要它成为UUID 对象。

标签: python postgresql sqlalchemy


【解决方案1】:

您使用修饰类型作为列类型。另一组文档解释得更清楚一点:https://docs.sqlalchemy.org/en/14/faq/sqlexpressions.html#faq-sql-expression-string

   from sqlalchemy import TypeDecorator, Integer

 
   class MyFancyType(TypeDecorator):
       impl = Integer

       def process_literal_param(self, value, dialect):
           return "my_fancy_formatting(%s)" % value

   from sqlalchemy import Table, Column, MetaData

      tab = Table('mytable', MetaData(), Column('x', MyFancyType()))

【讨论】:

    猜你喜欢
    • 2018-05-21
    • 2011-06-04
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 2015-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-06-06
    相关资源
    最近更新 更多