在Django / Algorithm中复制模型实例及其相关对象,用于重复地复制对象 [英] Duplicating model instances and their related objects in Django / Algorithm for recusrively duplicating an object
问题描述
我有的图书
,章节
和页面
。他们都是由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屋!