Дублирование образцовых экземпляров и их связанных объектов в Django / Алгоритм для recusrively дублирование объекта

35
задан Serjik 19 December 2015 в 07:49
поделиться

5 ответов

Это больше не работает в Django 1.3, когда CollectedObjects был удален. См. changeset 14507

, я отправил свое решение на Django Snippets. Это базируется в большой степени на django.db.models.query.CollectedObject код, используемый для удаления объектов:

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
16
ответ дан Bufke 27 November 2019 в 07:07
поделиться

Я думаю, что Вы были бы более довольны более простой моделью данных, также.

это действительно верно, что Страница находится в некоторой Главе, но различной книге?

userMe = User( username="me" )
userYou= User( username="you" )
bookMyA = Book( userMe )
bookYourB = Book( userYou )

chapterA1 = Chapter( book= bookMyA, author=userYou ) # "me" owns the Book, "you" owns the chapter?

chapterB2 = Chapter( book= bookYourB, author=userMe ) # "you" owns the book, "me" owns the chapter?

page1 = Page( book= bookMyA, chapter= chapterB2, author=userMe ) # Book and Author aggree, chapter doesn't?

кажется, что Ваша модель слишком сложна.

я думаю, что Вы были бы более довольны чем-то более простым. Я просто предполагаю это, так как я не делаю Вашего знать всю проблему.

class Book(models.Model)
    name = models.CharField(...)

class Chapter(models.Model)
    name = models.CharField(...)
    book = models.ForeignKey(Book)

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

Каждая страница имеет отличное авторство. Каждая глава, тогда, имеет набор авторов, как делает книгу. Теперь можно копировать Книгу, Главу и Страницы, присвоив клонированные Страницы новому Автору.

Действительно, Вы могли бы хотеть иметь many-many отношения между Page и Главой, позволяя Вам иметь несколько копий просто Page, не клонируя книгу и Главу.

1
ответ дан S.Lott 27 November 2019 в 07:07
поделиться

Я не попробовал его в django, но Python , deepcopy мог бы просто работать на Вас

РЕДАКТИРОВАНИЕ:

можно определить пользовательское поведение копии для моделей при реализации функций:

__copy__() and __deepcopy__()
8
ответ дан Sergey Golovchenko 27 November 2019 в 07:07
поделиться

Если в создаваемой вами базе данных всего пара копий, я обнаружил, что вы можете просто использовать кнопку «Назад» в интерфейсе администратора, изменить необходимые поля и снова сохранить экземпляр. Это сработало для меня в тех случаях, когда, например, мне нужно создать коктейль «буравчик» и «буравчик водки», где единственная разница заключается в замене названия и ингредиента. Очевидно, это требует небольшого предвидения данных и не так мощно, как переопределение копии / глубокой копии django, но для некоторых это может помочь.

3
ответ дан 27 November 2019 в 07:07
поделиться

Вот простой способ скопировать ваш объект.

В основном:

(1) установите для идентификатора исходного объекта значение None:

book_to_copy.id = None

(2) измените атрибут «author» и сохраните ojbect:

book_to_copy .author = new_author

book_to_copy.save ()

(3) INSERT выполняется вместо UPDATE

(это не касается смены автора на странице - я согласен с комментариями относительно реструктуризации модели)

9
ответ дан 27 November 2019 в 07:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: