SQLAlchemy:如何扩展混合属性?

2024-09-27 00:17:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用的是一个MSSQL数据库,它既不能控制数据库的设置,也不能控制其中的(只读)数据。在SQLAlchemy中有一个表是这样表示的:

class pdAnlage(pdBase):
    __tablename__ = "Anlage"
    typ = Column(CHAR(4), primary_key=True)
    nummer = Column(CHAR(4), primary_key=True)

在访问数据库时,我需要一个属性“name”,它只是“typ”和“nummer”的连接,它们之间有一个点。所以我这样做了:

^{pr2}$

看起来很简单,工作如期。不过,有两个注意事项,一个是一般性的,一个是特别的。一般的一个:表很大,我想查询一下Anlage.名称,如下所示:

db.query(Anlage).filter(Anlage.name.like('A%.B'))
db.query(Anlage).filter(Anlage.name == 'X.Y')

这是可行的,但效率低下,因为在执行测试之前,SQL server必须首先连接(大型)表的所有“typ”和“nummer”列。所以我定义了一个类方法:

    @classmethod
    def name_like(self, pattern):
        p = pattern.split('.', 2)
        if len(p) == 1 or not p[1]:
            return self.typ.like(p[0])
        else:
            return and_(self.typ.like(p[0]), self.nummer.like(p[1]))

这不雅观,但它做得很好。重载“==”和“like()”会更好,有办法吗?在

现在是特殊情况:name和typ列都可以在DB中包含尾随空格。但是name属性不能有空格,特别是在点之前。所以我试着把混合财产的名字改成这样:

    @hybrid_property
    def name(self):
        return self.typ.rstrip() + '.' + self.nummer.rstrip()

因为alchemt rim()无法翻译msstrth()函数。我怎么才能做到呢?在


Tags: keynameself数据库truedbreturn属性
1条回答
网友
1楼 · 发布于 2024-09-27 00:17:27

您可以实现一个custom comparator,它以一种特殊的方式(以及其他必要的方式)处理字符串操作数:

from sqlalchemy.ext.hybrid import Comparator

_sep = '.'


def _partition(s):
    typ, sep, nummer = s.partition(_sep)
    return typ, nummer


class NameComparator(Comparator):

    def __init__(self, typ, nummer):
        self.typ = typ
        self.nummer = nummer
        super().__init__(func.rtrim(typ) + _sep + func.rtrim(nummer))

    def operate(self, op, other, **kwgs):
        if isinstance(other, str):
            typ, nummer = _partition(other)
            expr = op(self.typ, typ, **kwgs)

            if nummer:
                expr = and_(expr, op(self.nummer, nummer, **kwgs))

            return expr

        else:
            # Default to using the "slow" method of concatenating first that
            # hides the columns from the index created for the primary key.
            return op(self.__clause_element__(), other, **kwgs)

并将其与混合属性一起使用:

^{pr2}$

相关问题 更多 >

    热门问题