639đź‘Ť
Just change the primary key of your object and run save().
obj = Foo.objects.get(pk=<some_existing_pk>)
obj.pk = None
obj.save()
If you want auto-generated key, set the new key to None.
More on UPDATE/INSERT here.
Official docs on copying model instances: https://docs.djangoproject.com/en/2.2/topics/db/queries/#copying-model-instances
164đź‘Ť
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:
blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1
blog.pk = None
blog.save() # blog.pk == 2
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.
- [Django]-Why does Django's render() function need the "request" argument?
- [Django]-Use Python standard logging in Celery
- [Django]-How do I use an UpdateView to update a Django Model?
64đź‘Ť
Be careful here. This can be extremely expensive if you’re in a loop of some kind and you’re retrieving objects one by one. If you don’t want the call to the database, just do:
from copy import deepcopy
new_instance = deepcopy(object_you_want_copied)
new_instance.id = None
new_instance.save()
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.
- [Django]-Django, Turbo Gears, Web2Py, which is better for what?
- [Django]-Django-nonrel + Django-registration problem: unexpected keyword argument 'uidb36' when resetting password
- [Django]-Macros in django templates
54đź‘Ť
Use the below code :
from django.forms import model_to_dict
instance = Some.objects.get(slug='something')
kwargs = model_to_dict(instance, exclude=['id'])
new_instance = Some.objects.create(**kwargs)
- [Django]-Determine variable type within django template
- [Django]-405 "Method POST is not allowed" in Django REST framework
- [Django]-Python Asyncio in Django View
23đź‘Ť
There’s a clone snippet here, which you can add to your model which does this:
def clone(self):
new_kwargs = dict([(fld.name, getattr(old, fld.name)) for fld in old._meta.fields if fld.name != old._meta.pk]);
return self.__class__.objects.create(**new_kwargs)
- [Django]-Why is logged_out.html not overriding in django registration?
- [Django]-How to force Django models to be released from memory
- [Django]-Adding django admin permissions in a migration: Permission matching query does not exist
22đź‘Ť
How to do this was added to the official Django docs in Django1.4
https://docs.djangoproject.com/en/1.10/topics/db/queries/#copying-model-instances
The official answer is similar to miah’s answer, but the docs point out some difficulties with inheritance and related objects, so you should probably make sure you read the docs.
- [Django]-Printing Objects in Django
- [Django]-Django admin and MongoDB, possible at all?
- [Django]-How do I POST with jQuery/Ajax in Django?
13đź‘Ť
I’ve run into a couple gotchas with the accepted answer. Here is my solution.
import copy
def clone(instance):
cloned = copy.copy(instance) # don't alter original instance
cloned.pk = None
try:
delattr(cloned, '_prefetched_objects_cache')
except AttributeError:
pass
return cloned
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.
- [Django]-Visual Editor for Django Templates?
- [Django]-How to make two django projects share the same database
- [Django]-How do you detect a new instance of the model in Django's model.save()
7đź‘Ť
This is yet another way of cloning the model instance:
d = Foo.objects.filter(pk=1).values().first()
d.update({'id': None})
duplicate = Foo.objects.create(**d)
- [Django]-Handling race condition in model.save()
- [Django]-Django py.test does not find settings module
- [Django]-How can I temporarily disable a foreign key constraint in MySQL?
5đź‘Ť
setting pk to None is better, sinse Django can correctly create a pk for you
object_copy = MyObject.objects.get(pk=...)
object_copy.pk = None
object_copy.save()
- [Django]-ForeignKey to abstract class (generic relations)
- [Django]-No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model
- [Django]-Cannot set Django to work with smtp.gmail.com
3đź‘Ť
This does an in-memory copy that you can mutate independently.
original = CheckoutItem(title="test", ...)
copy = CheckoutItem()
for f in CheckoutItem._meta.fields:
setattr(copy, f.attname, getattr(original, f.attname))
Or, as a method:
def clone(self):
"""Returns a clone of this instance."""
clone = self.__class__()
for f in self.__class__._meta.fields:
setattr(clone, f.attname, getattr(self, f.attname))
return clone
- [Django]-Nginx doesn't serve static
- [Django]-Django – No module named _sqlite3
- [Django]-Best way to integrate SqlAlchemy into a Django project
0đź‘Ť
To clone a model with multiple inheritance levels, i.e. >= 2, or ModelC below
class ModelA(models.Model):
info1 = models.CharField(max_length=64)
class ModelB(ModelA):
info2 = models.CharField(max_length=64)
class ModelC(ModelB):
info3 = models.CharField(max_length=64)
Please refer the question here.
- [Django]-'pip' is not recognized as an internal or external command
- [Django]-Celery missed heartbeat (on_node_lost)
- [Django]-Speeding up Django Testing
0đź‘Ť
Try this
original_object = Foo.objects.get(pk="foo")
v = vars(original_object)
v.pop("pk")
new_object = Foo(**v)
new_object.save()
- [Django]-Paginate relationship in Django REST Framework?
- [Django]-How can I create a deep clone of a DB object in Django?
- [Django]-How do I match the question mark character in a Django URL?
0đź‘Ť
There is a package that can do this which creates a UI within the django admin site: https://github.com/RealGeeks/django-modelclone
pip install django-modelclone
Add "modelclone" to INSTALLED_APPS and import it within admin.py.
Then, whenever you want to make a model clonable, you just replace "admin.ModelAdmin" in the given admin model class "modelclone.ClonableModelAdmin". This results in a "Duplicate" button appearing within the instance details page for that given model.
- [Django]-Django Rest Framework custom response message
- [Django]-Printing Objects in Django
- [Django]-How to test auto_now_add in django
0đź‘Ť
If you have a OneToOneField
then you should do it this way:
tmp = Foo.objects.get(pk=1)
tmp.pk = None
tmp.id = None
instance = tmp
- [Django]-How to print BASE_DIR from settings.py from django app in terminal?
- [Django]-Constructing Django filter queries dynamically with args and kwargs
- [Django]-How do I remove Label text in Django generated form?
0đź‘Ť
This simple process works fine for me:
foo_obj = Foo.objects.get(pk="foo")
foo_values = foo_obj.__dict__
foo_values.pop('_state')
foo_values.pop('id')
foo_new_obj = Foo(**foo_values)
foo_new_obj.save()
- [Django]-Warning: Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'
- [Django]-Django Rest Framework Conditional Field on Serializer
- [Django]-How to get the name of current app within a template?