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

后端 未结 17 990
名媛妹妹
名媛妹妹 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条回答
  •  -上瘾入骨i
    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
    

提交回复
热议问题