我正在开发一个项目,该项目使用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
并调用对象显示它们仍然在数据库中,并且他们仍然拥有“Sub Company 2'作为其父级。” >
所有这些问题都可以通过调用Company.objects.rebuild()
来修复,它将树恢复到正确的位置 - 但是这个项目的生产就绪版本可以有一个批次的数据数据库,因为这是一个整表活动,所以它会非常昂贵。关于我可以做些什么来解决这个问题的任何想法?
答案 0 :(得分:2)
好吧,我找到了一种让它发挥作用的方法。我不是简单地删除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