2012-11-30 32 views
13

Tôi đang sử dụng Flask-SQLAlchemy và tôi đang cố gắng viết hybrid method trong mô hình gốc trả về số lượng con, vì vậy tôi có thể sử dụng nó để lọc, sắp xếp, v.v. Dưới đây là một số mã được rút gọn của những gì tôi đang cố gắng:SQLAlchemy - Viết phương pháp lai cho số đếm trẻ

# 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 

Tôi đang gặp hai vấn đề ở đây. Thứ nhất, tôi không biết chính xác những gì để trở lại trong "CHILD_COUNT thư (cls)", trong đó có trở thành một biểu thức SQL ... Tôi nghĩ rằng nó phải là một cái gì đó giống như

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

nhưng tôi không chắc chắn rồi. Một vấn đề khác mà tôi có là tôi không thể nhập lớp Child từ parent.py, vì vậy tôi không thể sử dụng mã đó. Có cách nào để sử dụng một chuỗi cho điều này? Ví dụ,

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

Cuối cùng, tôi sẽ muốn thay đổi phương thức để một cái gì đó như:

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

... nhưng bây giờ, tôi chỉ cố gắng để có được điều này để làm việc. Rất cám ơn bất cứ ai có thể giúp tôi với điều này, như tôi đã cố gắng tìm ra điều này trong một thời gian dài.

Trả lời

16

Mã bên dưới hiển thị tất cả.

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) 
+0

Ah, cảm ơn bạn rất nhiều! Bạn đã giúp tôi cuối cùng tìm ra điều này. – fimbul

+0

Đây chính xác là tôi đang tìm kiếm! Cảm ơn! – Stanislav

-3

Tôi nghĩ rằng bạn chỉ có thể sử dụng đồng bằng ol' len và hybrid_property để lấy số liệu:

@hybrid_property 
def child_count(self): 
    return len(self.children) 

Từ doc, mà có vẻ như nó sẽ làm các trick, trừ khi tôi đang thiếu cái gì?

duggars = db.session.query(Parent).filter(Parent.child_count > 17) 
+0

Nó không phải là hybrid_property hợp lệ vì 'len' không phải là hoạt động hợp lệ SQLAlchemy trên mối quan hệ. – davidism

Các vấn đề liên quan