在Django / Algorithm中复制模型实例及其相关对象,用于重复地复制对象 [英] Duplicating model instances and their related objects in Django / Algorithm for recusrively duplicating an object

查看:1046
本文介绍了在Django / Algorithm中复制模型实例及其相关对象,用于重复地复制对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有的图书章节页面。他们都是由django.db导入的用户

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

from django.db import models

class Book(models.Model)
    author = models.ForeignKey('auth.User')

class Chapter(models.Model)
    author = models.ForeignKey('auth.User')
    book = models.ForeignKey(Book)

class Page(models.Model)
    author = models.ForeignKey('auth.User')
    book = models.ForeignKey(Book)
    chapter = models.ForeignKey(Chapter)

我想做的是重复现有的并更新它的用户给别人皱纹是我也想复制所有相关的模型实例到 - 所有它是页面以及

What I'd like to do is duplicate an existing Book and update it's User to someone else. The wrinkle is I would also like to duplicate all related model instances to the Book - all it's Chapters and Pages as well!

查看页面时,事情变得非常棘手> - 新的页面不仅需要更新他们的作者字段,而且还需要指向新的章节对象!

Things get really tricky when look at a Page - not only will the new Pages need to have their author field updated but they will also need to point to the new Chapter objects!

Django是否支持开箱即用的方式?复制模型的通用算法是什么样的?

Does Django support an out of the box way of doing this? What would a generic algorithm for duplicating a model look like?

干杯,

John

更新:

上面给出的类只是一个例子来说明问题我已经有了!

The classes given above are just an example to illustrate the problem I'm having!

推荐答案

在已删除CollectedObjects时,这不再适用于Django 1.3。请参见更改集14507

This no longer works in Django 1.3 as CollectedObjects was removed. See changeset 14507

我在Django Snippets上发布了我的解决方案。它主要依赖于 django.db.models.query.CollectedObject 用于删除对象的代码:

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

这篇关于在Django / Algorithm中复制模型实例及其相关对象,用于重复地复制对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆