2009-05-28 9 views
6

Właśnie przeszedłem introspekcję dość nieprzyjemnego schematu z aplikacji CRM z sqlalchemy. Wszystkie tabele mają na nich usuniętą kolumnę i chciałem automatycznie filtrować wszystkie te encje i relacje oflagowane jako usunięte. Oto co wymyśliłem:Właściwy sposób automatycznego filtrowania zapytań 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 

I jest używany tak:

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 jest klasa, który jest mapowany do tabeli sprzężenia między e-maili i innych modułów, którymi są związany z.

Oto przykład odwzorowującym:

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 

Daje mi to, co chcę, że mam odfiltrowane wszystkie usunięte kontakty. Mogę też użyć tego jako argumentu query_class do dynamic_loader w moich mappers - Jednak ...

  1. Czy istnieje lepszy sposób to zrobić, nie jestem naprawdę szczęśliwy z wywiercenie z wewnętrznych o compicated klasie jak Query, jak ja.
  2. Czy ktoś rozwiązał to w inny sposób, niż może to udostępnić?

Odpowiedz

7

Możesz mapować do zaznaczenia. Tak:

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

Bardzo miło, nie wiedziałem o tym! –

+0

Po prostu próbowałem to zrobić (na innym stole) i to nie zadziałało. Mam: TypeError: Obiekt "Table" nie jest iterable Czy jest jakiś pomysł? –

+0

Mój zły, pierwszym parametrem do wyboru jest lista kolumn/tabel podobnych do obiektów, więc email_join powinien znajdować się na liście. Naprawię to. –

0

Pomyślę sprawdzając, czy możliwe było tworzenie widoków dla tych tabel, które odfiltrować usuniętych elementów, a następnie może być w stanie przyporządkować bezpośrednio do tego widoku zamiast tabeli bazowej, przynajmniej do operacji związanych z zapytaniami. Jednak nigdy tego nie próbowałem!

Powiązane problemy