Python SQLAlchemy:如何扩展混合属性?

Python SQLAlchemy:如何扩展混合属性?,python,sql-server,sqlalchemy,Python,Sql Server,Sqlalchemy,我使用的是一个MSSQL数据库,既不能控制数据库设置,也不能控制其中的(只读)数据。SQLAlchemy中有一个表是这样表示的: class pdAnlage(pdBase): __tablename__ = "Anlage" typ = Column(CHAR(4), primary_key=True) nummer = Column(CHAR(4), primary_key=True) db.query(Anlage).filter(Anlage.name.like

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

class pdAnlage(pdBase):
    __tablename__ = "Anlage"
    typ = Column(CHAR(4), primary_key=True)
    nummer = Column(CHAR(4), primary_key=True)
db.query(Anlage).filter(Anlage.name.like('A%.B'))
db.query(Anlage).filter(Anlage.name == 'X.Y')
    @hybrid_property
    def name(self):
        return self.typ.rstrip() + '.' + self.nummer.rstrip()
在访问数据库时,我需要一个属性“name”,它只是“typ”和“numer”的一个串联,它们之间有一个点。所以我这样做了:

    @hybrid_property
    def name(self):
        return self.typ + '.' + self.nummer
看起来很简单,工作正常。不过有两个警告,一个是一般警告,一个是特殊警告。一般情况:表非常大,我想对Anlage.name进行查询,如下所示:

class pdAnlage(pdBase):
    __tablename__ = "Anlage"
    typ = Column(CHAR(4), primary_key=True)
    nummer = Column(CHAR(4), primary_key=True)
db.query(Anlage).filter(Anlage.name.like('A%.B'))
db.query(Anlage).filter(Anlage.name == 'X.Y')
    @hybrid_property
    def name(self):
        return self.typ.rstrip() + '.' + self.nummer.rstrip()
这是可行的,但效率很低,因为在进行测试之前,SQL server首先必须连接(大型)表的所有“typ”和“numer”列。所以我定义了一个类方法,如下所示:

    @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属性的名称,如下所示:

class pdAnlage(pdBase):
    __tablename__ = "Anlage"
    typ = Column(CHAR(4), primary_key=True)
    nummer = Column(CHAR(4), primary_key=True)
db.query(Anlage).filter(Anlage.name.like('A%.B'))
db.query(Anlage).filter(Anlage.name == 'X.Y')
    @hybrid_property
    def name(self):
        return self.typ.rstrip() + '.' + self.nummer.rstrip()
这不起作用,因为SQLAlchemy不知道如何将rstrip()python方法转换为MSSQL RTRIM()函数。如何实现这一点?

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

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

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

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

    @name.comparator
    def name(cls):
        return NameComparator(cls.typ, cls.nummer)

哇,酷!我希望必须深入到实际的(特定于DB的)SQL代码,但这要好得多(当然,必须在hybrid_属性中丢失rstrip()位)。我不明白的是:它按预期工作,但当我打印出生成的SQL时,我看不到任何rtrim函数调用。只是关于typ和nummer的两个比较。这是为什么?我没有看到在您自己的实现中使用它们,所以我跳过了它们,但是如果您确实需要它们,请将它们添加到
operate()
方法中。当用作要选择的属性时,
\uuu init\uuuu()
中对
rtrim()
的调用用于形成混合表达式。请注意,如果在比较时在列周围添加rtrim调用,则会再次从主键索引中隐藏它们。好的一点是,我不会将rtrim包含在比较位中。既然我的代码可以按预期工作,我就必须试着理解文档中关于它为什么工作的内容。