Flask SQLAlchemy query with concatenated columns

岁酱吖の 提交于 2021-01-04 05:31:29

问题


I have a models like this:

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)

I want to get the full_name method in a query, I try it like it:

user = db.session.query(User.full_name()).all()

But I get this error message:

TypeError: full_name() missing 1 required positional argument: 'self'

Then I try to call the function without brackets:

user = db.session.query(User.full_name).all()

Then I got this error message:

sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<function User.full_name at 0x7f265960aae8>'

So, what is the correct way to query full_name() method in the User model..?


回答1:


You need to create two hybrid attributes. A property that defines full_name on an instance and an expression that defines full_name on the class (for querying) and which depends on the property.

This is pure sqlalchemy, but the hybrid attributes should be the same in 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()

Edit: As Ilja observes, in this case a single method is sufficient, if we use '+' instead of string formatting:

class User(Base):
    ...

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

This works because sqlalchemy maps the + operator to the database's CONCAT function, so the expression decorator is not required.




回答2:


You can use @classmethod.

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)

    @classmethod
    def full_name_filter(cls, fname, lname):
        return (cls.first_name == fname, cls.last_name == lname)

Then

user = db.session.query(User).filter(*User.full_name_filter("first", "last")).all()


来源:https://stackoverflow.com/questions/57842652/flask-sqlalchemy-query-with-concatenated-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!