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
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]
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?).
一种可能的方法是使用dictalchemy :
new_instance = InstanceModel(**old_instance.asdict())
try this out
@classmethod
def clone(cls,tempversion,**kwargs):
attributestoremove=["tempversion","id"]
relationshipAttributes = cls.get_relationshipAttributes()
kwargs = { key:(None if value=='nan' else value) for key,value in kwargs.items() if hasattr(cls, key) and key not in relationshipAttributes and\
key not in attributestoremove}
kwargs["tempversion"]=tempversion
record = cls(**kwargs)
db.session.add(record)
db.session.commit()
return record
try:
db.session.commit()
except IntegrityError:
db.session.rollback()
record = None
return record
This method will clone any sqlalchemy db object. Add it to your model's class. Please note the the id of the new object will be created during commit (see comment):
def clone(self):
d = dict(self.__dict__)
d.pop("id") # get rid of id
d.pop("_sa_instance_state") # get rid of SQLAlchemy special attr
copy = self.__class__(**d)
db.session.add(copy)
# db.session.commit() if you need the id immediately
return copy
I put together this function to clone objects. It does not assign a primary key, but it will set the existing primary keys to None
and they are assigned by the autoincement (if set) once flushed to the database.
from sqlalchemy.orm.session import make_transient
from sqlalchemy import inspect
def clone_sql_object(obj, session):
# remove the object from the session (set its state to detached)
session.expunge(obj)
# make it transient (set its state to transient)
make_transient(obj)
# now set all primary keys to None so there are no conflicts later
for pk in inspect(obj).mapper.primary_key:
setattr(obj, pk.name, None)
return obj
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.