I want to create a method on a Django model, call it model.duplicate()
, that duplicates the model instance, including all the foreign keys pointing to it. I kno
You can create new instance and save it like this
def duplicate(self):
kwargs = {}
for field in self._meta.fields:
kwargs[field.name] = getattr(self, field.name)
# or self.__dict__[field.name]
kwargs.pop('id')
new_instance = self.__class__(**kwargs)
new_instance.save()
# now you have id for the new instance so you can
# create related models in similar fashion
fkeys_qs = self.fkeys.all()
new_fkeys = []
for fkey in fkey_qs:
fkey_kwargs = {}
for field in fkey._meta.fields:
fkey_kwargs[field.name] = getattr(fkey, field.name)
fkey_kwargs.pop('id')
fkey_kwargs['foreign_key_field'] = new_instance.id
new_fkeys.append(fkey_qs.model(**fkey_kwargs))
fkeys_qs.model.objects.bulk_create(new_fkeys)
return new_instance
I'm not sure how it'll behave with ManyToMany fields. But for simple fields it works. And you can always pop the fields you are not interested in for your new instance.
The bits where I'm iterating over _meta.fields may be done with copy but the important thing is to use the new id
for the foreign_key_field
.
I'm sure it's programmatically possible to detect which fields are foreign keys to the self.__class__
(foreign_key_field
) but since you can have more of them it'll better to name the one (or more) explicitly.