2017-06-08 18 views
0

SQLAlchemyを使用してアプリケーションを開発していますが、少し問題があります。 ORMが提供する可読性を維持しながら、クエリによって返されたすべてのモデルに対してメソッドを実行し、すべてのモデルを単一のSQLクエリで作成したいと考えています。SQLAlchemyのモデルのメソッドを使用した一括更新

この方法は非常に簡単で、外部データに依存せず、それ以上クエリを作成しません。一括更新のすべてのモデルで同じ正確な値が使用されている場合はうまくいくので、値そのものを一度だけ評価する必要があります。ここで

は私のモデルです:

class Item(db.Model): 
    last_fetch = db.Column(db.DateTime) 

    def refresh(self): 
     self.last_fetch = datetime.utcnow() 

私は、クエリによって返されるすべてのモデルにrefresh()関数を呼び出すしたいと思います - 例のためのそれはItem.query.all()だと仮定しましょう。

私はそれらを反復処理し、各モデルにメソッドを実行しますが、それはそれらのそれぞれに別々のクエリを実行しますすることができます

items = Item.query.all() 

for item in items: 
    item.refresh() 

または私はしかし、私は今、移動した作品次のことを行うことができますモデルからコードへの私のrefresh()ロジックそうでない場合は、単にそのメソッドを呼び出しますこと:

items = Item.query.all() 

items.update({Item.last_fetch: datetime.utcnow()}) 

は、よりよい解決策はありますか?どのようにしてORMがモデルメソッドを保持したままバルクで実行できるようにする、モデル上に「スマートな」メソッドを定義する方法ですか?

よろしくお願いいたします。

答えて

0

SQLAlchemyは照会されたオブジェクトを__init__ではなく__new__を使用して再作成します。
モデル上で__new__を無効にするか、Constructors and Object Initializationで説明されている@orm.reconstructorデコレータが動作するかどうか試してみてください。

class Item(db.Model): 
last_fetch = db.Column(db.DateTime) 

@orm.reconstructor 
def set_last_fetch_on_load(self): 
    self.last_fetch = datetime.datetime.now() 

__new__オーバーライド:

class Item(db.Model): 
last_fetch = db.Column(db.DateTime) 

def __new__(cls, *args, **kwargs): 
    obj = object.__new__(cls, *args, **kwargs) 
    obj.last_fetch = datetime.datetime.now() 
    return obj 

を注:はそれをテストしていない再構成を使用して

+0

モデルがインスタンス化されるたびに日付がリセットされるのではないでしょうか?それは私が望むものではありません。私は手動で起動できるようにしたい(私はこれを特定の条件のもとでのみ呼び出す)。 –

+0

アイテムを照会するたびに日付が更新されます。したがって、データベースからフェッチする度にあなたが特定の条件の下でこれを行う必要がある場合、私はあなたが書いたものがうまくいくと思って、私の答えを無視することができます。 – Cicero

関連する問題