问题
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