1

私は、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 を使用して削除後に 'Sub Company 2' を復元する必要がありますが、'Tiny Companies' はテンプレートでレンダリングされません (ただし、オブジェクトをすばやくダッキングしshellて呼び出すと、オブジェクトがまだデータベースにあることが示されます。彼らはまだ親として 'Sub Company 2' を持っています。

これらの問題はすべてCompany.objects.rebuild()、ツリーを適切な表現に復元する を呼び出すことで修正できますが、このプロジェクトの本番対応バージョンでは、データベースに大量のデータが含まれている可能性があり、それはテーブル全体のアクティビティであるため、非常に困難です。高い。この問題を解決するために何ができるかについてのアイデアはありますか?

4

1 に答える 1

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
于 2014-08-09T16:55:20.567 に答える