2012-11-30 13 views
13

Flask-SQLAlchemy kullanıyorum ve sahip olduğu çocuk sayısını döndüren bir üst modele hybrid method yazmayı deniyorum, böylece filtreleme için kullanabilirim, sıralama, vb. Denediğim şeyin bazı soyulmuş kodları aşağıda verilmiştir:SQLAlchemy - Çocuk sayısı için bir melez yöntem yazılıyor

# 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 

Burada iki sorunla karşılaşıyorum. İlk olarak, ben bir SQL ifadesi olmak zorundadır "CHILD_COUNT (cls)", içinde dönmek için tam olarak ne olduğunu bilmiyorum ... Ben

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

gibi bir şey olması gerektiğini düşünüyorum ama değilim emin. Sahip olduğum başka bir sorun da Child sınıfını parent.py'den içe aktaramayacağım, bu yüzden bu kodu yine de kullanamıyorum. Bunun için bir dize kullanmanın bir yolu var mı? Örneğin,

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

Sonunda, ben böyle bir şey için yöntemini değiştirmek istersiniz:

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

... ama şimdi, sadece bu işe almaya çalışıyorum. Bu konuda bana yardımcı olabileceklere çok teşekkürler, şimdi bunu uzun zamandır çözmeye çalışıyorum. doc itibaren

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

, bir şey eksik sürece, hile yaparım benziyor:

cevap

16

Aşağıdaki kod, tümünü gösterir.

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, çok teşekkür ederim! Sonunda bana bunu anlamana yardım ettin. – fimbul

+0

Bu tam olarak arıyordum! Teşekkürler! – Stanislav

-3

Ben sadece sayım sonucuna varmak için düz ol' len ve hybrid_property kullanabilir miyiz?

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

Geçerli bir hybrid_property değil, çünkü '' ', ilişkide geçerli bir SQLAlchemy işlemi değil. – davidism