【问题标题】:SQLAlchemy - Writing a hybrid method for child countSQLAlchemy - 为子计数编写混合方法
【发布时间】:2012-11-18 09:12:08
【问题描述】:

我正在使用 Flask-SQLAlchemy,我正在尝试在父模型中编写一个 hybrid method,它返回它拥有的子模型的数量,因此我可以将它用于过滤、排序等。这里有一些剥离记录我正在尝试的代码:

# parent.py
from program.extensions import db
from sqlalchemy.ext.hybrid import hybrid_method

class Parent(db.Model):
    __tablename__ = 'parents'
    parent_id = db.Column(db.Integer, primary_key=True)

    name = db.Column(db.String(80))
    children = db.relationship('Child', backref='parent', lazy='dynamic')

    def __init__(self, name):
        self.name = name

    @hybrid_method
    def child_count(self):
        return self.children.count()

    @child_count.expression
    def child_count(cls):
        return ?????

# child.py
from program.extensions import db
from program.models import Parent

class Child(db.Model):
    __tablename__ = 'children'
    child_id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey(Parent.parent_id))

    name = db.Column(db.String(80))
    time = db.Column(db.DateTime)

    def __init__(self, name, time):
        self.name = name
        self.time = time

我在这里遇到了两个问题。一方面,我不知道在“child_count(cls)”中究竟要返回什么,它必须是一个 SQL 表达式......我认为它应该类似于

return select([func.count('*'), from_obj=Child).where(Child.parent_id==cls.parent_id).label('Child count')

但我不确定。我遇到的另一个问题是我无法从 parent.py 导入 Child 类,因此无论如何我都无法使用该代码。有没有办法为此使用字符串?例如,

select([func.count('*'), from_obj='children').where('children.parent_id==parents.parent_id').label('Child count')

最终,我想将方法​​更改为:

def child_count(cls, start_time, end_time):
    # return the number of children whose "date" parameter is between start_time and end_time

...但是现在,我只是想让它发挥作用。非常感谢任何可以帮助我的人,因为我已经尝试了很长时间了。

【问题讨论】:

    标签: python sqlalchemy flask


    【解决方案1】:

    下面的代码说明了一切。

    class Parent(Base):
        __tablename__ = 'parents'
        # ...
    
        @hybrid_property
        def child_count(self):
            #return len(self.children)   # @note: use when non-dynamic relationship
            return self.children.count()# @note: use when dynamic relationship
    
        @child_count.expression
        def child_count(cls):
            return (select([func.count(Child.child_id)]).
                    where(Child.parent_id == cls.parent_id).
                    label("child_count")
                    )
    
        @hybrid_method
        def child_count_ex(self, stime, etime):
            return len([_child for _child in self.children
                if stime <= _child.time <= etime ])
    
        @child_count_ex.expression
        def child_count_ex(cls, stime, etime):
            return (select([func.count(Child.child_id)]).
                    where(Child.parent_id == cls.parent_id).
                    where(Child.time >= stime).
                    where(Child.time <= etime).
                    label("child_count")
                    )
    
    
    # usage of expressions:
    stime, etime = datetime.datetime(2012, 1, 1), datetime.datetime(2012, 1, 31)
    qry = session.query(Parent)
    #qry = qry.filter(Parent.child_count > 2)
    qry = qry.filter(Parent.child_count_ex(stime, etime) > 0)
    

    【讨论】:

    • @xxx.expression 函数应该有一个@classmethod 装饰器吗?我注意到您使用 cls 变量而不是 self
    • @franc0is:不,你不应该。它由 sqlalchemy 处理——它是一个类级别的表达式。
    • 如何使用这种混合方法进行 IS Null 检查?
    • @flexxxit:与您在任何其他表达式中所做的方式完全相同。您认为挑战在哪里?
    猜你喜欢
    • 1970-01-01
    • 2011-06-27
    • 2022-01-22
    • 2018-07-19
    • 2016-01-12
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多