I want to clone a SQLAlchemy object:
I tried:
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)
but it just updates the old object.
Here is the code of products.save
function:
class Service(object): __model__ = None def save(self, model): self._isinstance(model) db.session.add(model) db.session.commit() return model
¶ The SQLAlchemy ORM, in order to map to a particular table, needs there to be at least one column denoted as a primary key column; multiple-column, i.e. composite, primary keys are of course entirely feasible as well.
To create a composite primary key, set primary_key to True on each column involved in the key. A boolean argument when set to False adds NOT NULL constraint while creating a column. Its default value is True .
Return the first result of this Query or None if the result doesn't contain any row. first() applies a limit of one within the generated SQL, so that only one primary entity row is generated on the server side (note this may consist of multiple result rows if join-loaded collections are present).
Most ORMs require that objects have some kind of primary key defined because the object in memory must correspond to a uniquely identifiable row in the database table; at the very least, this allows the object can be targeted for UPDATE and DELETE statements which will affect only that object's row and no other.
This should work:
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)
For sqlalchemy 1.3 I ended up using a helper function.
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.columns.keys()] 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
With this function you can solve the above problem using:
product_obj = products.all()[0] # Get the product from somewhere. cloned_product_obj = clone_model(product_obj, product_uid='something')
Depending on your use-case you might want to remove the call to db.session.commit()
from this function.
This answer is based on https://stackoverflow.com/a/13752442/769486 (How to get a model’s columns?) and How do I get the name of an SQLAlchemy object's primary key? (How do I get a model’s primary keys?).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With