Login

Clone model mixin

Author:
zakj
Posted:
December 31, 2008
Language:
Python
Version:
1.0
Score:
6 (after 6 ratings)

Add this as a superclass of any Django model to allow making copies of instances of that model:

class Entry(models.Model, CloneableMixin):
    [...]

e = Entry.objects.get(...)
e_clone = e.clone()
e_clone.title = 'Cloned Entry'
e.save()

The new object is saved during the clone process and ManyToMany relations are copied as well.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import copy


class ClonableMixin(object):
    def clone(self):
        """Return an identical copy of the instance with a new ID."""
        if not self.pk:
            raise ValueError('Instance must be saved before it can be cloned.')
        duplicate = copy.copy(self)
        # Setting pk to None tricks Django into thinking this is a new object.
        duplicate.pk = None
        duplicate.save()
        # ... but the trick loses all ManyToMany relations.
        for field in self._meta.many_to_many:
            source = getattr(self, field.attname)
            destination = getattr(duplicate, field.attname)
            for item in source.all():
                destination.add(item)
        return duplicate

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 8 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 9 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 3 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 4 months ago
  5. Help text hyperlinks by sa2812 1 year, 5 months ago

Comments

rizumu (on October 22, 2009):

On django 1.2, this snippet works for me only if i set both pk and id to None:

# Setting both pk and id to None tricks Django into thinking this is a new object.
duplicate.pk = None
duplicate.id = None

#

Please login first before commenting.