This is pretty obvious, just auto adds a filter that ignores the deleted at, but, I think this is a very hard thing to get right, especially with joins and whatnot. This works, but I would like to know what's the recommended idiom? I looked at this stack overflow question:class NoDeletedQuery(Query):def __new__(cls, *args, **kwargs):if args and hasattr(args[0][0], "deleted_at"):return Query(*args, **kwargs).filter_by(deleted_at=None)else:return object.__new__(cls)Session = scoped_session(sessionmaker(query_cls=NoDeletedQuery))
active_accts_q = (select([accounts_t]).where(accounts_t.c.deleted_at == None).alias())class Account(Base):__table__ = active_accts_qdef soft_delete(self):self.deleted_at = func.clock_timestamp()
account.soft_delete()Session.commit()
ObjectDeletedError: Instance '<Account at 0x102b2d390>' has been deleted, or its row is otherwise not present.
I wanted to know some views about the soft-delete (anti?) pattern and whether or not I'm going about it the right way in my code base.We have a piece of code:This is pretty obvious, just auto adds a filter that ignores the deleted at, but, I think this is a very hard thing to get right, especially with joins and whatnot. This works, but I would like to know what's the recommended idiom? I looked at this stack overflow question:class NoDeletedQuery(Query):def __new__(cls, *args, **kwargs):if args and hasattr(args[0][0], "deleted_at"):return Query(*args, **kwargs).filter_by(deleted_at=None)else:return object.__new__(cls)Session = scoped_session(sessionmaker(query_cls=NoDeletedQuery))
class NoDeletedQuery(Query):"""Subclass query and provide a pre-fabricated WHERE clause that isapplied to all queries.It uses the enable_assertions() method available in SA v0.5.6 andabove to bypass the Query object's usual checks."""def get(self, ident):# override get() so that the flag is always checked in the# DB as opposed to pulling from the identity map. - this is optional.return Query.get(self.populate_existing(), ident)def __iter__(self):return Query.__iter__(self._criterion_filter())def from_self(self, *ent):# override from_self() to automatically apply# the criterion too. this works with count() and# others.return Query.from_self(self._criterion_filter(), *ent)
def _criterion_filter(self):# get the mapper heremzero = self._mapper_zero()# if its a mapped class and our criteria is satisfied..if mzero is not None and 'deleted_at' in mzero.mapped_table.c:table = mzero.mapped_tablenot_deleted_q = select([table]).where(table.c.deleted_at == None)# need an alias to use this as a mapper because some dbs don't# support anonymous sub queries and sqlalchemy enforces.not_deleted_q = not_deleted_q.alias()return self.enable_assertions(False).select_from(not_deleted_q)else:return self
--
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To post to this group, send email to sqlal...@googlegroups.com.
To unsubscribe from this group, send email to sqlalchemy+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.