Worth noting that this quotes Django 1.2, we're now up to Django 1.4. Haven't tested whether or not this works, but don't use this answer without being sure that it works for you.
– JoeOct 4 '12 at 11:37

6

Works fine in 1.4.1 This is probably one of those things that will continue to work for a long while.
– frnhrOct 28 '12 at 13:13

7

I had to set both obj.pk and obj.id to make this work in Django 1.4
– Petr PellerJan 10 '14 at 18:00

The Django documentation for database queries includes a section on copying model instances. Assuming your primary keys are autogenerated, you get the object you want to copy, set the primary key to None, and save the object again:

In this snippet, the first save() creates the original object, and the second save() creates the copy.

If you keep reading the documentation, there are also examples on how to handle two more complex cases: (1) copying an object which is an instance of a model subclass, and (2) also copying related objects, including objects in many-to-many relations.

Note on miah's answer: Setting the pk to None is mentioned in miah's answer, although it's not presented front and center. So my answer mainly serves to emphasize that method as the Django-recommended way to do it.

Historical note: This wasn't explained in the Django docs until version 1.4. It has been possible since before 1.4, though.

Possible future functionality: The aforementioned docs change was made in this ticket. On the ticket's comment thread, there was also some discussion on adding a built-in copy function for model classes, but as far as I know they decided not to tackle that problem yet. So this "manual" way of copying will probably have to do for now.

It does the same thing as some of these other answers, but it doesn't make the database call to retrieve an object. This is also useful if you want to make a copy of an object that doesn't exist yet in the database.

This works great if you have an object, you can deep copy the original object before making changes make changes to the new object and save it. Then you can do some condition checking and depending on if they pass, i.e. the object is in another table that you are checking, you can set the new_instance.id = original_instance.id and save :) Thanks!
– radtekSep 25 '14 at 21:43

1

This does not work if the model has multiple inheritance levels.
– David CheungNov 19 '15 at 2:21

3

And does not work with 'through' relations either
– Martin B.Mar 22 '16 at 11:24

1

on my case I wanted to create a clone method for the model, which would use the "self" variable and I cannot simply just set the self.pk None, so this solution worked like a charm. I thought about the model_to_dict solution below, but it requires an extra step and it would have the same issue with the through relations, which I have to deal manually anyway so it has no major impact for me.
– Anderson SantosAug 18 '16 at 14:18

Note: this uses solutions that aren't officially sanctioned in the Django docs, and they may cease to work in future versions. I tested this in 1.9.13.

The first improvement is that it allows you to continue using the original instance, by using copy.copy. Even if you don't intend to reuse the instance, it can be safer to do this step if the instance you're cloning was passed as an argument to a function. If not, the caller will unexpectedly have a different instance when the function returns.

copy.copy seems to produce a shallow copy of a Django model instance in the desired way. This is one of the things I did not find documented, but it works by pickling and unpickling, so it's probably well-supported.

Secondly, the approved answer will leave any prefetched results attached to the new instance. Those results shouldn't be associated with the new instance, unless you explicitly copy the to-many relationships. If you traverse the the prefetched relationships, you will get results that don't match the database. Breaking working code when you add a prefetch can be a nasty surprise.

Deleting _prefetched_objects_cache is a quick-and-dirty way to strip away all prefetches. Subsequent to-many accesses work as if there never was a prefetch. Using an undocumented property that begins with an underscore is probably asking for compatibility trouble, but it works for now.