我正在使用flask-sqlalchemy和python 2.7。
我正在尝试创建一个可以在查询中使用的属性。我已经知道我应该使用hybrid_property
来使用相应的表达式但是我在表达式中获取timedelta
对象时遇到了问题。
我想要执行的查询类似于Article.query.filter(Article.language == language).order_by(Article.popularity.desc())
带
from math import exp
from datetime import datetime, timedelta
from sqlalchemy.ext.hybrid import hybrid_property
class Article(db.Model):
__tablename__ = 'articles'
article_id = db.Column(db.Integer, primary_key=True)
# ...
language = db.Column(db.String(64), default='en')
date_time = db.Column(db.DateTime, default=datetime.utcnow)
readers_frac = db.Column(db.Float, default=0.)
@hybrid_property
def popularity(self):
# compute the popularity based on the readers_frac and the time in minutes since the article was published
min_since_published = (datetime.utcnow() - self.date_time).total_seconds()/60.
popularity_decay = exp(-(min_since_published**2 / (2.*1832.4**2)))
return self.readers_frac*popularity_decay
@popularity.expression
def popularity(cls):
# compute the popularity based on the readers_frac and the time in minutes since the article was published
min_since_published = (datetime.utcnow() - cls.date_time).seconds/60.
popularity_decay = exp(-(min_since_published**2 / (2.*1832.4**2)))
return cls.readers_frac*popularity_decay
但是,在尝试计算AttributeError: Neither 'BinaryExpression' object nor 'Comparator' object has an attribute 'seconds'
时,我收到错误min_since_published
。任何提示?谢谢!
更新
我通过将所有内容更改为sqlalchemy.func
表达式来修复它,即它使用
import sqlalchemy as sa
@popularity.expression
def popularity(cls):
# compute the popularity based on the readers_frac and the time in minutes since the article was published
min_since_published = sa.func.timestampdiff(sa.text('MINUTE'), cls.date_time, sa.func.utc_timestamp())
popularity_decay = sa.func.exp(-(sa.func.pow(min_since_published, 2) / 6730009.))
return cls.readers_frac*popularity_decay
答案 0 :(得分:1)
我已经了解到它真的取决于你为此使用的数据库后端以及它提供的功能。例如,sqlite不起作用,因为数据库本身没有能力回答查询,但mysql确实如此。然后它真的只是看看函数看起来像原始的mysql查询语句,并将其转换为sqlalchemy.func
表达式。这有效:
import sqlalchemy as sa
@popularity.expression
def popularity(cls):
# compute the popularity based on the readers_frac and the time in minutes since the article was published
min_since_published = sa.func.timestampdiff(sa.text('MINUTE'), cls.date_time, sa.func.utc_timestamp())
popularity_decay = sa.func.exp(-(sa.func.pow(min_since_published, 2) / 6730009.))
return cls.readers_frac*popularity_decay