2010-09-10 156 views
1

度日eagerload_all()在一定时间内的孩子我有一个表帖子它存储3种后,主题回复评论。每个人都有其父母ID。如何设置过滤器在SQLAlchemy的

# Single table inheritance 
class Post(Base): 
    __tablename__ = 'posts' 
    id = Column(Integer, primary_key=True) 
    parent_id = Column(Integer, ForeignKey('posts.id')) 
    discriminator = Column(String(1)) 
    content = Column(UnicodeText) 
    added_at = Column(DateTime) 
    __mapper_args__ = {'polymorphic_on': discriminator} 

class Topic(Post): 
    replies = relation("Reply") 
    __mapper_args__ = {'polymorphic_identity': 't'} 

class Reply(Post): 
    comments = relation("Comment") 
    __mapper_args__ = {'polymorphic_identity': 'r'} 

class Comment(Post): 
    __mapper_args__ = {'polymorphic_identity': 'c'} 

而且我使用eagerload_all()来获取所有的答复和意见属于一个话题:

session.query(Topic).options(eagerload_all('replies.comments')).get(topic_id) 

我的问题是,如果我想只得到答复和这些答复的意见在某个时间段内,例如,本周或本月。我应该如何使用过滤器来实现这一目标?

谢谢

回答

1

采用eagerload_all只会查询对象Topicchildren立即,而在第一次请求Replies和/或Comments,但因为你的Topic对象加载到会话,其所有相关的孩子也会被加载。这给了你第一个选项:

选项1:在Python代码,而不是database筛选:
基本上创建一个类似于

class Topic(Post): 
    ... 
    def filter_replies(self, from_date, to_date): 
     return [r for r in self.replies 
       if r.added_at >= from_date 
       and r.added_at <= to_date] 

Topic对象的一个​​方法。然后,你可以做类似Replies上的代码来过滤Comments或这些的任意组合。你明白了。

选项2:在database级过滤:
为了实现这一点,你不需要加载Topic对象,而是直接在Reply/Comment过滤。下面的查询返回所有Reply对于给定Topic带有日期过滤器:

topic_id = 1 
from_date = date(2010, 9, 5) 
to_date = date(2010, 9, 15) 
q = session.query(Reply) 
q = q.filter(Reply.parent_id == topic_id) 
q = q.filter(Reply.added_at >= from_date) 
q = q.filter(Reply.added_at <= to_date) 
for r in q.all(): 
    print "Reply: ", r 

版本的注释,你才能克服SQL语句产生问题,因为需要一个别名是只是一点点更多地参与所有的对象映射到同一个表名:

topic_id = 1 
from_date = date(2010, 9, 5) 
to_date = date(2010, 9, 15) 
ralias = aliased(Reply) 
q = session.query(Comment) 
q = q.join((ralias, Comment.parent_id == ralias.id)) 
q = q.filter(ralias.parent_id == topic_id) 
q = q.filter(Comment.added_at >= from_date) 
q = q.filter(Comment.added_at <= to_date) 
for c in q: 
    print "Comment: ", c 

很明显,你可以创建一个既能撕成小块组合成一个更全面的查询功能。
为了实现this weekthis month查询类型,您可以将这些过滤器转换为如上所示的日期范围或使用SA的expression.func功能。