Cloning an instance of a mapped class

155 views
Skip to first unread message

Mike Conley

unread,
Jul 29, 2009, 2:43:59 PM7/29/09
to sqlal...@googlegroups.com
I have a need to clone an instance of a mapped class and insert the new instance in my database with only minor changes to attributes. To do this I want to create a new instance of the class with all non-key attributes copied from the old instance. Primary keys and foreign keys will be populated at insert time via normal processes for any instance.

Here is a function I wrote to clone the non-key attributes to a new instance. Does this make sense or might I stumble into an unseen abyss somewhere, or is there an easier way to do this? (I did not use copy.copy() because I only want the non-key attributes copied)
None of the classes involve polymorphism which is one area I thought there might be trouble.
All of our classes use the default declarative __init__(), so the statement  new = cls()  is valid in all cases.

def clone_instance(old):
    cls = old.__class__
    tbl = cls.__table__
    new = cls()
    for c in tbl.c:
        if c.primary_key or c.foreign_keys:
            continue
        setattr(new, c.name, getattr(old,c.name))
    return new


usage is something like this

obj = session.query(SomeClass).get(someid)
newobj = clone_instance(obj)
newobj.someattribute = some different value
session.add(newobj)
session.commit()

This seems to work for the simple cases I ran so far, just wondering if there are any hidden problems or simplifications.

--
Mike Conley

BigJon

unread,
Aug 3, 2009, 2:52:51 PM8/3/09
to sqlalchemy
I'd love to find a reasonable way of cloning an instance, even with
the caveat that one could only copy attributes that are no primary or
foreigh key related.

Still, I to make that code "work" w/newer versions of SA:

def clone_instance(old):
new = type(old)()
m = sa_orm.object_mapper(old)
for c in m.columns:

thatsanice...@mac.com

unread,
Aug 3, 2009, 4:59:46 PM8/3/09
to sqlal...@googlegroups.com
Hi,

I'm circling around an answer for a problem but am not quite getting
it. I have two tables: Plugging and Cartridge. Plugging has a to-one
relation to Cartridge, and the inverse relation is to-many. Cartridge
has a field called "number" and plugging has a field called "active".
I want to build a query to retrieve a single plugging, and this works
for me:

plugging, cart = session.query(Plugging,
Cartridge).filter(Cartridge.number ==
cartNo).filter(Plugging.cartridge_pk ==
Cartridge.pk).filter(Plugging.active == True).one()

This seems overly complicated - I shouldn't need to specify the
primary keys (pk) since the foreign keys are already defined (I'm
using autoload with postgresql). My first attempt at a query was this:

plugging = session.query(Plugging).filter(Plugging.cartridge.number ==
cartNo).one()

...but that turned out to be too optimistic (ignore for the moment
that I left out the "active" filter). What is the best practice for
simplifying the first query?

Cheers,
Demitri

Michael Bayer

unread,
Aug 3, 2009, 11:39:11 PM8/3/09
to sqlal...@googlegroups.com
this is standard relation() stuff thats documented in the ORM tutorial
in "Querying with Joins".
Reply all
Reply to author
Forward
0 new messages