For sqlalchemy 1.3 I ended up using a helper function.
- It copies all the non-primary-key columns from the input model to a new model instance.
- It allows you to pass data directly as keyword arguments.
- It leaves the original model object unmodified.
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?).