Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This no longer works in Django 1.3 as CollectedObjects was removed. See <a href="http://code.djangoproject.com/changeset/14507" rel="noreferrer">changeset 14507</a></p> <p><a href="http://www.djangosnippets.org/snippets/1282/" rel="noreferrer">I posted my solution on Django Snippets.</a> It's based heavily on the <a href="http://code.djangoproject.com/browser/django/trunk/django/db/models/query.py#L33" rel="noreferrer"><code>django.db.models.query.CollectedObject</code></a> code used for deleting objects:</p> <pre><code>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 </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload