2012-11-30 3 views
13

저는 Flask-SQLAlchemy를 사용하고 있는데, 가지고있는 자식 수를 반환하는 부모 모델에 hybrid method을 쓰려고하는데, 필터링을 위해 사용할 수 있습니다. 정렬, 등등. 여기에 몇 가지 내가 노력하고 코드를 벗겨 내려 :SQLAlchemy - 하위 개수에 대한 하이브리드 메서드 작성

# 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 

여기에 두 가지 문제가 실행 중입니다. 하나, 나는이 SQL 표현식 수있는 "CHILD_COUNT (CLS)"에 반환 정확히 모른다 ... 나는

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 

...하지만 지금은, 난 그냥이 작업을 얻기 위해 노력하고있어. 나는 이것을 오랫동안 알아 내려고 노력했기 때문에이 일을 도와 줄 수있는 사람에게 큰 감사를 전한다. 다큐먼트에서

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

, 내가 뭔가를 누락하지 않는 한이 트릭을 할 것 같습니다

답변

16

아래 코드는이 모든 것을 보여줍니다.

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

아, 정말 고마워요! 너는 마침내 이것을 이해하도록 도와 주었다. – fimbul

+0

이것은 정확히 내가 찾고 있었던 것이다! 감사! – Stanislav

-3

나는 그냥 수를 얻기 위해 일반 팔자 '렌과 hybrid_property를 사용할 수있을 것 같아요?

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

'len'은 관계에 대한 유효한 SQLAlchemy 연산이 아니므로 유효한 hybrid_property가 아닙니다. – davidism

관련 문제