如何在 sqlalchemy 模型中使用 hybrid_property 进行过滤以解码列中的值?

How to filter with hybrid_property in sqlaclhemy model to decode value from column?

我不明白如何使用 hybrid properties 或者它们的局限性是什么。
我有一个模型,其中列以 ascii 格式存储域名。其中一些是 idna 编码表示的,如 utf-8:

domain.com
xn--d1acufc.xn--p1ai # домен.рф
...

我想用一个界面过滤域名。通过 ASCII 字符串过滤没有什么困难,但是非 ascii 是另一回事。 我想将 "рф" 之类的子字符串传递给 filter_by_name() 并获得预期结果 - 在这种情况下使用 xn--d1acufc.xn--p1ai

的 1 条记录
class SomeModel(Base):
    __tablename__ = "table"
    name = Column(String(255))

    @hybrid_property
    def decoded_name(self):
        return self.name.encode("utf-8").decode("idna")

    @decoded_name.expression
    def decoded_name(cls):
        return cls.name.encode("utf-8").decode("idna")

    @classmethod
    def filter_by_name(cls, substring: str):
        with sessionmaker.begin() as s:
            query = s.query(SomeModel)

            if substring.isascii():
                condition = cls.name.like(f"%{substring}%")
            else:
                condition = cls.decoded_name.like(f"%{substring}%")

            query = query.filter(condition)
        return query.all()

购买我收到以下错误消息。看来我应该将 sqlclhemy func 与对应的 SQL 函数一起使用,但是...如果我需要 python 像 encode/decode 这样的例程怎么办?

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with SomeModel.name has an attribute 'encode'

定义表达式时:

    @decoded_name.expression
    def decoded_name(cls):
        return cls.name.encode("utf-8").decode("idna")

您处于数据库级别,而不是 python 级别。所以你应该使用数据库操作员,但在你的情况下它可能很棘手甚至不可能。根据数据库的不同,您的实现会有所不同。对于 PostgreSQL,您可能应该使用 convert 函数:https://www.postgresql.org/docs/8.2/functions-string.html and maybe this idna extension (that should be installed in a database): https://github.com/dyninc/postgresql-idn。 然后你的表情看起来像这样:

    @decoded_name.expression
    def decoded_name(cls):
        return func.idn_idna_encode(func.convert(cls.name, <one_of_utf-8_conversion_type>))