[英]How to clone a SQLAlchemy object with new primary key
I want to clone a SQLAlchemy object:我想克隆一个 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.但它只是更新旧的 object。
Here is the code of products.save
function:这是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. 对于sqlalchemy 1.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
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. 根据您的用例,您可能希望从此函数中删除对db.session.commit()
的调用。
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? 这个答案基于https://stackoverflow.com/a/13752442/769486 (如何获取模型的列?)以及如何获取SQLAlchemy对象的主键名称? (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.此方法将克隆任何 sqlalchemy db 对象。 Add it to your model's class.将它添加到模型的类中。 Please note the the id of the new object will be created during commit (see comment):请注意新对象的 id 将在提交期间创建(见评论):
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.我把这个 function 放在一起克隆对象。 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.它不分配主键,但它会将现有的主键设置为None
并且一旦刷新到数据库,它们就会由自动增强(如果设置)分配。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.