私のFlask-Restfulアプリケーションには多数の「オブジェクト」があります。アプリの最初のバージョンでは、これは動作のない単純なデータ構造 、Dictsとして実装されたもの、またはDictsのリストです。SQLAlchemyオブジェクトインスタンスと属性の等価性の比較
これらの「オブジェクト」の属性は変更される可能性があります。私はジェネレータ機能を使用して変更を追跡し、サーバー送信イベント(SSE)を介してWebクライアントに警告します。 これは、追跡されるオブジェクトの「古い」コピーを維持し、それを最新の状態と比較することによって機能します。
次のバージョンのアプリケーションでは、SQLAlchemyを使用してSQLite DBから「オブジェクト」を作成します。 オブジェクトはSQLAlchemyの宣言的なクラスまたはそのようなクラスのリストとして実装されるようになりました。
属性の同等性に基づいて「古い」インスタンスと「新しい」インスタンスを比較するには、 SQLAlchemyオブジェクトに__eq__
のオーバーライドを追加する必要がありました。すなわち、属性が同じ値を有するとき、インスタンスは等しい/不変であると見なされる。 (私はこの質問の一番下にサンプルコードを掲載しています)。
これは技術的には機能しますが、アーキテクチャ上の警鐘を喚起します。誤った方向に航行していますか?私はSQAlchemyオブジェクトに__eq__
と__ne__
オーバーライドを追加する場合
a)は、この原因は、私は後で が戻ってデータベースにオブジェクトを再永続化したい問題をSQLAlchemyのだろうか?
b)SQLAlchemyオブジェクトに到達するまでには、どのくらいの時間が必要ですか?「Pythonicベストプラクティス」はありますか?つまり、SQLAlchemyオブジェクトをビジネスロジック/ビヘイビア(DBパーシステンスとの接続が変更されていないなど)に拡張することはOK /正常ですか?または、データベースとサーバー間の単純なDTOとしてのみ使用し、他のオブジェクトにビジネスロジックを使用する必要がありますか?
注:REST APIおよびSSEを介してクライアントに提示されるデータは、WebサーバーおよびDBの実装の詳細から抽象化する必要があるため、この質問の一部ではありません。 https://codereview.stackexchange.com/questions/93511/data-transfer-objects-vs-entities-in-java-rest-server-application http://www.mehdi-khalili.com/orm-anti-patterns-part-4-persistence-domain-model/
sqlalchemy id equality vs reference equality
class EqualityMixin(object):
# extended from the concept in :
# https://stackoverflow.com/questions/390250/elegant-ways-to-support-equivalence-equality-in-python-classes
def __eq__(self, other):
classes_match = isinstance(other, self.__class__)
a, b = deepcopy(self.__dict__), deepcopy(other.__dict__)
#compare based on equality our attributes, ignoring SQLAlchemy internal stuff
a.pop('_sa_instance_state', None)
b.pop('_sa_instance_state', None)
attrs_match = (a == b)
return classes_match and attrs_match
def __ne__(self, other):
return not self.__eq__(other)