更好地复制模型实例及相关模型的方法

1 投票
1 回答
1207 浏览
提问于 2025-04-18 15:55

我在寻找一种最快、最简单的方法来复制一个模型实例和相关的模型。我在这里这里找到了几种方法,但我觉得这些方法都是基于旧版的Django。

我用循环实现了这个功能,但有没有更好的方法呢?我尝试过django-forkit插件,但遇到了一个关于模型中有外键字段指向auth.User的问题。

模型:

class Book(Folder):
    filename = models.CharField(max_length=255)
    created_by = models.ForeignKey(User)

class Chapter(models.Model):
    book = models.ForeignKey(Book)
    name = models.CharField(max_length=255, db_index=True)

class Page(models.Model):
    book = models.ForeignKey(Book)
    attribute_value = hstore.DictionaryField(db_index=True)

复制函数:

    book = Book.objects.get(pk=node_id, created_by=request.user)
    chapters = Chapter.objects.filter(book=book)
    pages = Page.objects.filter(book=book)
    book.pk = None
    book.id = None
    book.filename = book.filename + "_copy"
    book.save()
    for chapter in chapters:
        chapter.book= book
        chapter.pk = None
        chapter.save()
    for page in pages:
        page.book= book
        page.pk = None
        page.save()

1 个回答

1

如果你的模型真的那么简单,我建议就保持现在的样子。

如果不是,或者你想做得更复杂一点;那么我个人比较喜欢的一种设计方式是,明确列出在复制操作中会受到影响的字段,然后逐个处理。这种做法可以避免你在模型的API上乱搞,从而可能导致你的代码无法升级。这样一来,你的模型也能清楚地说明在复制时会发生什么,这对于某些你可能不想复制的字段来说非常方便。例如:

class CopyableModel(models.Model):
    # these fields are persisted across copies
    _copy_concerns = ['title', 'author', 'body']

    def create_copy(self):
        attrs = {}
        for concern in self._copy_concerns:
           attrs[concern] = getattr(self, concern)

        # does this work?  Might have to access the CopyableModel definition in a different way...
        # Like self.__class__.objects.create( ...
        return CopyableModel.objects.create(**attrs)

你还可以稍微调整一下,以便处理多对多关系和其他关系。再次强调,不确定在你的具体情况下这样做是否值得,但在需要的时候,这是一种很好的可扩展的模式。

撰写回答