SQLAlchemy混合属性表达式datetime转换

时间:2016-07-06 14:31:37

标签: python sqlalchemy flask-sqlalchemy

我正在使用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表达式来修复它,即它使用

工作(使用mysql后端)
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

1 个答案:

答案 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