私たちは、tornadoとsqlalchemyを使用してアプリケーションのサービスを作成しています。アプリケーションはdjangoで書かれ、 "ソフト削除メカニズム"を使用します。つまり、基礎となるmysqlテーブルには削除がなかったということです。行を削除済みとしてマークするには、属性付きの「削除」をTrueに設定するだけです。しかし、サービスでは、sqlalchemyを使用しています。最初は、私たちのようなSQLAlchemyの自身によって作られたクエリで削除のチェックを追加しました:開発者がクエリで削除のチェックを欠場する傾向があるので、sqlalchemyを使用した「ソフト削除」システムの実装
customers = db.query(Customer).filter(not_(Customer.deleted)).all()
しかし、これは潜在的なバグの多くにつながります。そこで我々は、「プレフィルター」を行い、当社の問合せクラスで問い合わせるデフォルトを上書きすることを決めた:
class SafeDeleteMixin(Query):
def __iter__(self):
return Query.__iter__(self.deleted_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.deleted_filter(), *ent)
def deleted_filter(self):
mzero = self._mapper_zero()
if mzero is not None:
crit = mzero.class_.deleted == False
return self.enable_assertions(False).filter(crit)
else:
return self
これは、ここでSQLAlchemyのドキュメント上の溶液からインスピレーションを得た:
https://bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/PreFilteredQuery
しかし、我々はまだあります上記のようにフィルタと更新を行い、このクエリクラスを使用している場合のように、更新のためにフィルタを適用するときの更新はdelete=False
の基準を尊重しません。
db = CustomSession(with_deleted=False)()
result = db.query(Customer).filter(Customer.id == customer_id).update({Customer.last_active_time: last_active_time })
は、どのように私はここに似た何かをやったSQLAlchemyの
これは、削除せずにクエリを停止しません。これは重大です。全体のポイントは間違いを避けるためです。 – dusual
'customer_query()。filter(something).update(something2)'は、 'something'フィルタと共に削除フィルタを適用する必要があります。 – aitchnyu