web-dev-qa-db-ja.com

新しい主キーでsqlalchemy dbオブジェクトを複製する方法

Sqlalchemyオブジェクトを複製したい:

私はそれを試しました

product_obj = products.all()[0] #here products is service name

product_obj.product_uid = 'soemthing' #here product_uid is the pk of product model

products.save(product_obj)

old_objectのみを更新するだけです

これがproducts.save関数のコードです

class Service(object):

        __model__ = None

       def save(self, model):
            self._isinstance(model)
            db.session.add(model)
            db.session.commit()
            return model
26
Harshit Agarwal

これはうまくいくはずです:

product_obj = products.all()[0]

db.session.expunge(product_obj)  # expunge the object from session
make_transient(product_obj)  # http://docs.sqlalchemy.org/en/rel_1_1/orm/session_api.html#sqlalchemy.orm.session.make_transient

product_obj.product_uid = 'something'
db.session.add(product_obj)
24

Sqlalchemy 1.3では、ヘルパー関数を使用してしまいました。

  1. すべての非主キー列を入力モデルから新しいモデルインスタンスにコピーします。
  2. キーワード引数としてデータを直接渡すことができます。
  3. 元のモデルオブジェクトは変更されません。
_def clone_model(model, **kwargs):
    """Clone an arbitrary sqlalchemy model object without its primary key values."""
    # Ensure the model’s data is loaded before copying.
    model.id

    table = model.__table__
    non_pk_columns = [k for k in table.columns.keys() if k not in table.primary_key]
    data = {c: getattr(model, c) for c in non_pk_columns}
    data.update(kwargs)

    clone = model.__class__(**data)
    db.session.add(clone)
    db.session.commit()
    return clone
_

この関数を使用すると、次の方法で上記の問題を解決できます。

_product_obj = products.all()[0]  # Get the product from somewhere.
cloned_product_obj = clone_model(product_obj, product_uid='something')
_

ユースケースによっては、この関数からdb.session.commit()の呼び出しを削除することをお勧めします。


この回答は https://stackoverflow.com/a/13752442/769486 (モデルの列を取得する方法?)と SQLAlchemyオブジェクトのプライマリの名前を取得する方法)に基づいていますkey? (モデルの主キーを取得するにはどうすればよいですか?).

5
zwirbeltier

1つの可能なアプローチは、 dictalchemy を使用することです。

new_instance = InstanceModel(**old_instance.asdict())
3
Berislav Lopac