[英]Flask SQLAlchemy: How to find the primary key value before adding a new object to the session?
[英]How to clone a SQLAlchemy object with new primary key
我想克隆一个 SQLAlchemy object:
我试过:
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)
但它只是更新旧的 object。
这是products.save
function 的代码:
class Service(object):
__model__ = None
def save(self, model):
self._isinstance(model)
db.session.add(model)
db.session.commit()
return model
这应该工作:
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)
对于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
使用此功能,您可以使用以下方法解决上述问题:
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对象的主键名称? (如何获得模型的主键?)。
一种可能的方法是使用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
此方法将克隆任何 sqlalchemy db 对象。 将它添加到模型的类中。 请注意新对象的 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
我把这个 function 放在一起克隆对象。 它不分配主键,但它会将现有的主键设置为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.