Duplicating model instances and their related objects in Django / Algorithm for recusrively duplicating an object

后端 未结 17 912
名媛妹妹
名媛妹妹 2020-11-29 01:04

I\'ve models for Books, Chapters and Pages. They are all written by a User:

from django.db import models
         


        
相关标签:
17条回答
  • 2020-11-29 01:43

    Elaborated based on previous answers:

    def derive(obj):
        import copy
        from django.contrib.admin.utils import NestedObjects
        from django.db import DEFAULT_DB_ALIAS
        from django.db.models.fields.related import ForeignKey
        """
            Derive a new model instance from previous one,
            and duplicate all related fields to point to the new instance
        """
        obj2 = copy.copy(obj)
        obj2.pk = None
        obj2.save()
        collector = NestedObjects(using=DEFAULT_DB_ALIAS)
        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]]
                    )
                )
            })
    
        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.rel.to 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:
                    dupe_obj = copy.copy(obj)
                    setattr(dupe_obj, fk.name, obj2)
                    dupe_obj.pk = None
                    dupe_obj.save()
        return obj2
    
    0 讨论(0)
  • 2020-11-29 01:49

    Django does have a built-in way to duplicate an object via the admin - as answered here: In the Django admin interface, is there a way to duplicate an item?

    0 讨论(0)
  • 2020-11-29 01:52

    Suggestion of Julio Marins works! Thnx!

    For Django >= 2.* this line:

    if isinstance(f, ForeignKey) and f.rel.to in related_models:

    Should be replaced with:

    if isinstance(f, ForeignKey) and f.remote_field.model in related_models:

    0 讨论(0)
  • 2020-11-29 01:53

    In Django 1.5 this works for me:

    thing.id = None
    thing.pk = None
    thing.save()
    
    0 讨论(0)
  • 2020-11-29 01:54

    Here's an easy way to copy your object.

    Basically:

    (1) set the id of your original object to None:

    book_to_copy.id = None

    (2) change the 'author' attribute and save the ojbect:

    book_to_copy.author = new_author

    book_to_copy.save()

    (3) INSERT performed instead of UPDATE

    (It doesn't address changing the author in the Page--I agree with the comments regarding re-structuring the models)

    0 讨论(0)
提交回复
热议问题