How do I clone a Django model instance object and save it to the database?
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
clone a Django model instance object and save it to the another model having same fields
The best way would be to hash the result from .get() query.
obj = Foo.objects.get(pk=<some_existing_pk>)
data = dict(obj.values()[0])
# pop the pk
data.pop('id')
# pass the dict as **kwargs
Foo2.objects.create(**data).save()
How to copy a Django Model Instance and all related data
For this particular case, you can bulk_create
the contributors
:
contributor_names = list(book.contributors.values_list('name', flat=True))
book.id = None
book.save()
# create the contributor object with the name and new book id.
contributors = [Contributor(name=name, book_id=book.id) for name in contributor_names]
Contributor.objects.bulk_create(contributors)
Duplicate Django model instance without modifying python object
Refreshing from db with correct id do the job, Downside is having to do multiple database call.
def duplicate_from_db(self):
old_pk = self.pk # storing for refreshing latter
self.pk = None
self._state.adding = True
self.save()
new_pk = self.pk
self.pk = old_pk
self.refresh_from_db()
return MyModel.objects.get(pk=new_pk)
Duplicating model instances and their related objects in Django / Algorithm for recusrively duplicating an object
This no longer works in Django 1.3 as CollectedObjects was removed. See changeset 14507
I posted my solution on Django Snippets. It's based heavily on the django.db.models.query.CollectedObject
code used for deleting objects:
from django.db.models.query import CollectedObjects
from django.db.models.fields.related import ForeignKey
def duplicate(obj, value, field):
"""
Duplicate all related objects of `obj` setting
`field` to `value`. If one of the duplicate
objects has an FK to another duplicate object
update that as well. Return the duplicate copy
of `obj`.
"""
collected_objs = CollectedObjects()
obj._collect_sub_objects(collected_objs)
related_models = collected_objs.keys()
root_obj = None
# Traverse the related models in reverse deletion order.
for model in reversed(related_models):
# Find all FKs on `model` that point to a `related_model`.
fks = []
for f in model._meta.fields:
if isinstance(f, ForeignKey) and f.rel.to in related_models:
fks.append(f)
# Replace each `sub_obj` with a duplicate.
sub_obj = collected_objs[model]
for pk_val, obj in sub_obj.iteritems():
for fk in fks:
fk_value = getattr(obj, "%s_id" % fk.name)
# If this FK has been duplicated then point to the duplicate.
if fk_value in collected_objs[fk.rel.to]:
dupe_obj = collected_objs[fk.rel.to][fk_value]
setattr(obj, fk.name, dupe_obj)
# Duplicate the object and save it.
obj.id = None
setattr(obj, field, value)
obj.save()
if root_obj is None:
root_obj = obj
return root_obj
For django >= 2 there should be some minimal changes. so the output will be like this:
def duplicate(obj, value=None, field=None, duplicate_order=None):
"""
Duplicate all related objects of obj setting
field to value. If one of the duplicate
objects has an FK to another duplicate object
update that as well. Return the duplicate copy
of obj.
duplicate_order is a list of models which specify how
the duplicate objects are saved. For complex objects
this can matter. Check to save if objects are being
saved correctly and if not just pass in related objects
in the order that they should be saved.
"""
from django.db.models.deletion import Collector
from django.db.models.fields.related import ForeignKey
collector = Collector(using='default')
collector.collect([obj])
collector.sort()
related_models = collector.data.keys()
data_snapshot = {}
for key in collector.data.keys():
data_snapshot.update(
{key: dict(zip([item.pk for item in collector.data[key]], [item for item in collector.data[key]]))})
root_obj = None
# Sometimes it's good enough just to save in reverse deletion order.
if duplicate_order is None:
duplicate_order = reversed(related_models)
for model in duplicate_order:
# Find all FKs on model that point to a related_model.
fks = []
for f in model._meta.fields:
if isinstance(f, ForeignKey) and f.remote_field.related_model in related_models:
fks.append(f)
# Replace each `sub_obj` with a duplicate.
if model not in collector.data:
continue
sub_objects = collector.data[model]
for obj in sub_objects:
for fk in fks:
fk_value = getattr(obj, "%s_id" % fk.name)
# If this FK has been duplicated then point to the duplicate.
fk_rel_to = data_snapshot[fk.remote_field.related_model]
if fk_value in fk_rel_to:
dupe_obj = fk_rel_to[fk_value]
setattr(obj, fk.name, dupe_obj)
# Duplicate the object and save it.
obj.id = None
if field is not None:
setattr(obj, field, value)
obj.save()
if root_obj is None:
root_obj = obj
return root_obj
How do I duplicate a django model instance, keeping a reference to the original?
article = get_some_article()
revision = article.revision
revision.parent = revision # Set the parent to itself
revision.content += " edited"
revision.pk = None
revision.save() # New revision with parent set to original
# Assuming you are keeping the latest revision reference in article you need to update that also.
article.revision = revision
article.save()
Django how to create, update and keep clone objects to another database for backup purpose?
finally I find out an solution. After reading django multiple database documentation we can use multiple database but can't keep clone object in our database. Let explain little bit assume you have two model teacher and student. You can use two separate database for teacher and student but you can't use another database for keep clone objects of your teacher and student model. So here we will use django siganls for keep clone objects in our replica_database. Signals will be triggered and create clone object whenever any objects create in our model. Here is my code:
settings.py
'default': {
'NAME': 'primary_database',
'ENGINE': 'django.db.backends.mysql',
'HOST': 'localhost',
'USER': 'root',
'PASSWORD': '',
},
'replica1_database': {
'NAME': 'replica1_database',
'ENGINE': 'django.db.backends.mysql',
'HOST': 'localhost',
'USER': 'root',
'PASSWORD': '', },
models.py:
from django.db.models.signals import post_save
from django.dispatch import receiver
class Contact(models.Model):
name = models.CharField(blank=True, null=True, max_length=100)
@receiver(post_save, sender=Contact, dispatch_uid="clone_objects")
def replica1_databse(sender, instance, created, **kwargs):
if created: #cerate clone object in our replica1 database
obj = instance
obj.save(using='replica1')
else: #updating clone object in our replica1 database
obj = Contact.objects.using('replica1').update(
name=instance.name)
Here I am triggering signals for create an clone objects in my replica1_database.
Now run python manage.py makemigrtions contact
and python manage.py migrate contact
this two migrations applied in your default database. This is the most important step ----> You have to run python manage.py migrate --database=replica1
This migrate applied for your replica1 database.
I Think it also an good idea to keep an backup database for avoid any unexcepted situation such as server down.
Related Topics
How to Make Image/Images Disappear in Pygame
What Is _Future_ in Python Used for and How/When to Use It, and How It Works
How to Check the Versions of Python Modules
When I Catch an Exception, How to Get the Type, File, and Line Number
Libxml Install Error Using Pip
How to Print Bold Text in Python
How to Determine the Language of a Piece of Text
Cannot Install Lxml on MAC Os X 10.9
Running Python on Windows for Node.Js Dependencies
Usage of Sys.Stdout.Flush() Method
Change User-Agent for Selenium Web-Driver
How to Find Numeric Columns in Pandas
How to Scroll Frame Using Mouse Wheel & Adding Horizontal Scrollbar
Log into Gmail Using Selenium in Python
Flask to Return Image Stored in Database