带有连接列的 Flask SQLAlchemy 查询

Gof*_*tty 2 python sqlalchemy flask-sqlalchemy

我有一个这样的模型:

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(64), index=True)
    last_name = db.Column(db.String(64), index=True)
    
    def full_name(self):
        return '%s %s' % (self.first_name, self.last_name)
Run Code Online (Sandbox Code Playgroud)

我想full_name在查询中获取该方法,我像这样尝试:

user = db.session.query(User.full_name()).all()
Run Code Online (Sandbox Code Playgroud)

但我收到此错误消息:

TypeError: full_name() missing 1 required positional argument: 'self'
Run Code Online (Sandbox Code Playgroud)

然后我尝试调用不带括号的函数:

user = db.session.query(User.full_name).all()
Run Code Online (Sandbox Code Playgroud)

然后我收到此错误消息:

sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<function User.full_name at 0x7f265960aae8>'
Run Code Online (Sandbox Code Playgroud)

那么,full_name()在 User 模型中查询方法的正确方法是什么..?

sna*_*erb 5

您需要创建两个混合属性full_name在实例上定义的属性和full_name在类上定义的表达式(用于查询)并且取决于属性。

这是纯sqlalchemy,但混合属性在flask-sqlalchemy中应该是一样的。

import sqlalchemy as sa
from sqlalchemy.ext import hybrid

class User(Base):
    __tablename__ = 'users' 
                                                                                                                                                                        
    id = sa.Column(sa.Integer, primary_key=True)
    first_name = sa.Column(sa.String)
    last_name = sa.Column(sa.String)

    @hybrid.hybrid_property
    def full_name(self):  
        return '%s %s' % (self.first_name, self.last_name)

    @full_name.expression
    def full_name(self): 
        return self.first_name + ' ' + self.last_name


users = session.query(User).filter_by(full_name='Joan Doe').all()
Run Code Online (Sandbox Code Playgroud)

编辑: 正如 Ilja 所观察到的,在这种情况下,如果我们使用'+'而不是字符串格式,一个方法就足够了:

class User(Base):
    ...

    @hybrid.hybrid_property
    def full_name(self):  
        return self.first_name + ' ' + self.last_name
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为 sqlalchemy 将+ 运算符映射到数据库的CONCAT函数,因此不需要表达式装饰器。

  • 在这种情况下,单个方法也可以:)(用于表达式的方法对两者都适用,我认为这甚至是文档中的示例)。 (2认同)