2009-05-28 6 views
6

Je viens d'introspecter un schéma assez méchant d'une application CRM avec sqlalchemy. Tous les tableaux ont une colonne supprimée sur eux et je voulais filtrer automatiquement toutes ces entités et les relations marquées comme supprimées. Voici ce que je suis venu avec:La bonne façon de filtrer automatiquement les requêtes SQLAlchemy?


class CustomizableQuery(Query): 
    """An overridden sqlalchemy.orm.query.Query to filter entities 

    Filters itself by BinaryExpressions 
    found in :attr:`CONDITIONS` 
    """ 

    CONDITIONS = [] 

    def __init__(self, mapper, session=None): 
     super(CustomizableQuery, self).__init__(mapper, session) 
     for cond in self.CONDITIONS: 
      self._add_criterion(cond) 

    def _add_criterion(self, criterion): 
     criterion = self._adapt_clause(criterion, False, True) 
     if self._criterion is not None: 
      self._criterion = self._criterion & criterion 
     else: 
      self._criterion = criterion 

Et il est utilisé comme ceci:

class UndeletedContactQuery(CustomizableQuery): 
    CONDITIONS = [contacts.c.deleted != True] 

    def by_email(self, email_address): 
     return EmailInfo.query.by_module_and_address('Contacts', email_address).contact 

    def by_username(self, uname): 
     return self.filter_by(twod_username_c=uname).one() 

class Contact(object): 
    query = session.query_property(UndeletedContactQuery) 

Contact.query.by_email('[email protected]') 

EmailInfo est la classe qui est mis en correspondance avec la table de jointure entre les e-mails et les autres modules qu'ils relatif à.

Voici un exemple d'un mappeur:

contacts_map = mapper(Contact, join(contacts, contacts_cstm), { 
    '_emails': dynamic_loader(EmailInfo, 
           foreign_keys=[email_join.c.bean_id], 
           primaryjoin=contacts.c.id==email_join.c.bean_id, 
           query_class=EmailInfoQuery), 
    }) 

class EmailInfoQuery(CustomizableQuery): 

    CONDITIONS = [email_join.c.deleted != True] 
    # More methods here 

Cela me donne ce que je veux dans ce que j'ai filtré tous les contacts supprimés. Je peux aussi l'utiliser comme argument QUERY_CLASS à dynamic_loader dans mes cartographes - Mais ...

  1. est-il une meilleure façon de faire, je ne suis pas vraiment content de farfouillé avec les internes d'une classe compicated comme interroger comme je suis.
  2. Est-ce que quelqu'un a résolu cela d'une manière différente qu'ils peuvent partager?

Répondre

7

Vous pouvez mapper vers une sélection. Comme ceci:

mapper(EmailInfo, select([email_join], email_join.c.deleted == False)) 
+0

Très bien, je ne savais pas à ce sujet! –

+0

J'ai juste essayé de faire ceci (sur une table différente) et cela n'a pas fonctionné. J'ai: TypeError: l'objet 'Table' n'est pas itérable Une idée pourquoi? –

+0

Mon mauvais, le premier paramètre à sélectionner est une liste de colonnes/objets de type table, donc email_join devrait être dans une liste. Je le réparerai. –

0

je considère voir s'il était possible de créer des vues pour ces tables qui filtrent les éléments supprimés, et alors vous pourriez être en mesure de cartographier directement à ce point de vue au lieu de la table sous-jacente, au moins pour les opérations d'interrogation. Cependant, je n'ai jamais essayé moi-même!

Questions connexes