2010-09-10 5 views
1

J'ai une table messages et magasins 3 types de poste, Sujet, Répondre et Commentaire. Chacun a son identifiant parent.Comment configurer le filtre pour amener les enfants à certaine période de temps par eagerload_all() à 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'} 

Et j'utilise eagerload_all() pour obtenir toutes les réponses et les commentaires appartiennent à un sujet:

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

Ma question est, si je veux que les réponses et les commentaires de ces réponses dans une certaine période de temps, par exemple, cette semaine, ou ce mois-ci. Comment dois-je utiliser un filtre pour y parvenir?

Merci

Répondre

1

L'utilisation de eagerload_all n'interroger pour la children d'un objet Topic immédiatement plutôt sur la première demande au Replies et/ou Comments, mais puisque vous chargez l'objet Topic dans la session, toute sa les enfants apparentés seront également chargés. Cela vous donne la première option:

Option 1: filtre dans le code python au lieu de database:
créer essentiellement une méthode sur l'objet Topic similaire à

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] 

Ensuite, vous pouvez faire la même code sur Replies pour filtrer Comments ou toute combinaison de ceux-ci. Vous avez eu l'idée.

Option 2: Filtrer sur le niveau database:
Pour ce faire, vous ne devez pas charger l'objet Topic, mais filtrer directement sur le Reply/Comment. Suite à la requête retourne tous Reply pour une donnée Topic avec un filtre Date:

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 

La version pour le commentaire est un peu plus impliqué que vous avez besoin d'un alias afin de surmonter le problème de génération d'instruction SQL que tous vos les objets sont mis en correspondance avec le même nom de la table:

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 

Évidemment, vous pouvez créer une fonction qui combinerait les deux peaces dans une requête plus complète.
Afin d'atteindre this week ou this month type de requêtes, vous pouvez soit convertir ces filtres dans une plage de dates comme indiqué ci-dessus ou utiliser la fonctionnalité expression.func de SA.

Questions connexes