【问题标题】:Getting django-mptt to play nice with django-reversion让 django-mptt 与 django-reversion 一起玩得很好
【发布时间】:2014-10-02 10:37:20
【问题描述】:

我正在开发一个项目,该项目使用 django-reversion 来跟踪更改并提供恢复到早期状态的能力,并使用 django-mptt 来处理一些树形模型。然而,删除和恢复功能有一些奇怪的行为。我正在使用如下所示的演示数据:

Big Company
    Sub Company 1
    Sub Company 2
      Tiny Company 1
      Tiny Company 2

我已经操纵 django-reversion 以便删除一个节点 也 将其所有子节点保存到修订版 - 因此,删除 Big Company 会删除整个树,然后将其还原(或实际上,任何子节点)也会恢复整个树。到目前为止,一切顺利。

但是,当我尝试删除/还原子节点时,事情开始变得奇怪。例如,删除“子公司 1”会导致“子公司 2”及其后代停止在模板中呈现(尽管奇怪的是,这种行为有些不一致)。或者,我是否应该在删除后使用 django-reversion 恢复“子公司 2”,“小公司”都不会在模板中呈现(尽管快速进入 shell 并调用对象表明它们仍在数据库中,并且他们仍然有“子公司 2”作为他们的母公司。

所有这些问题都可以通过调用 Company.objects.rebuild() 来解决,这会将树恢复到正确的表示形式——但是该项目的生产就绪版本可能在数据库中有 很多 数据,并且由于这是一项全桌活动,因此成本高得令人望而却步。关于我可以做些什么来解决这个问题的任何想法?

【问题讨论】:

    标签: django django-mptt django-reversion


    【解决方案1】:

    嗯,我找到了一种让它工作的方法。我不是简单地删除 MPTT 节点,而是将其移动到新的根位置。这会以一种似乎不会简单地删除节点的方式正确地重新组织树。当然,我希望能够在之后重新附加节点,因此我将父主键存储在补充修订元数据选项中。相关代码如下:

    class MPTT_Parent(models.Model):
        revision = models.OneToOneField(Revision)
        parent_id = models.IntegerField()
    
    def remove_company(obj):
        with transaction.atomic() and reversion.create_revision():
    
             #These lines are to preserve the integrity of the tree before deleting it
             #Objects deleted from django-mptt trees don't automatically update the positions
            if not obj.is_root_node():
                reversion.add_meta(MPTT_Parent,parent_id=obj.parent.id)
            obj.move_to(target=None,position='first-child')
    
            obj.save()
    
            #Save all associated descendant information into the revision
            for child in obj.get_descendants(include_self=False):
                child.save()
    
       obj.delete()
    
    def restore_company(version):
        #get the parent id.  If the parent has been deleted or was never set, 
        #keeps the node as root
        company = revert_object(version) #custom function that reverts given object
        try:
             parent = Company.objects.get(id=version.revision.mptt_parent.parent_id)
        except (ObjectDoesNotExist, AttributeError):
             pass
        else:
             company.move_to(target=parent,position='first-child')
    
        return company
    

    【讨论】:

      猜你喜欢
      • 2015-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-23
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 2011-04-30
      相关资源
      最近更新 更多