私は、Django の復帰とは逆に、シェルで行われたリビジョンが保存されないという問題に直面しています。
使用されているバージョン:
Django: v1.3.1
django-reversion: v1.5.7
モデルに加えられた変更を保存/破棄するために使用できるクラスを作成しました。
import reversion, datetime
class Execute:
model = None
delete_ids = []
def __init__(self, model):
self.model = model
if not reversion.is_registered(model):
reversion.register(model)
def update(self, n):
id = n.pk
if len(self.model.objects.filter(pk=id)) > 0:
m= self.model.objects.get(pk=id)
if len(reversion.get_for_object(m)) == 1: # Update newly inserted element
reversion.get_for_object(m).delete() # reversion list only 1 long.
with reversion.create_revision():
m=n
m.save()
else: # Update existing element. reversion list will be at least 2 long
if len(reversion.get_for_object(m)) == 0: # Add self as first revision.
with reversion.create_revision():
m.save()
with reversion.create_revision(): # Add updates
m=n
m.save()
def insert(self, n):
with reversion.create_revision():
n.pk = None
n.save()
return n.pk
def delete(self, n):
id = n.pk
if len(self.model.objects.filter(pk=id)) > 0:
m=self.model.objects.get(pk=id)
with reversion.create_revision():
m.save()
delete_ids.append(id)
m.delete()
def discard(self, n):
id = n.pk
if len(self.model.objects.filter(pk=id)) > 0:
m=self.model.objects.get(pk=id)
rev=reversion.get_for_object(m)
if len(rev) == 0:
return
if len(rev) == 1: #insert operation, then delete
m.delete()
else: #update operation, then revert
rev[len(rev)-1].revert()
rev.delete()
if len(reversion.get_deleted(self.model).filter(object_id=id)) > 0:
reversion.get_deleted(self.model).get(object_id=id).revert()
def save(self, n):
id = n.pk
if len(self.model.objects.filter(pk=id)) > 0:
m=self.model.objects.get(pk=id)
m.save()
reversion.get_for_object(m).delete()
if len(reversion.get_deleted(self.model).filter(object_id=id)) > 0:
reversion.get_deleted(self.model).get(object_id=id).delete()
次に、次のように使用します。
> my_execute=Execute(MyModel) m=MyModel.objects.get(pk=id)
>
> --modify something in m--
> my_execute.update(tm)
>
> --modify something else in m--
> my_execute.update(tm)
>
> --modify something else in m--
> my_execute.update(tm)
>
> my_execute.discard(tm) <-- Revert m to original
> or
> my_execute.save(tm) <-- Save new modifications
これらをシェル経由で実行すると完全に機能しますが、ビューで POST リクエストを実行すると一貫性がなくなります。
デバッグ時に、基本的にシェルで実行しているときに、登録したモデルが「save()」を実行するたびに、リスト「reversion.get_for_object(m)」が期待どおりに新しいリビジョンを追加することがわかりました。しかし、Djangoビューで同じことを実行すると、リストは期待どおりに更新されませんが、ビューコードの終わりに達したときにのみ発生するようです.
例: 既存のモデルを更新すると、次のような 2 つのエントリが表示されると予想されます。
>>> reversion.get_for_object(tm)
[]
>>> tm_execute.update(tm)
>>> reversion.get_for_object(tm)
[<Version: QGE__Power Sequencing fix__726__lalitb>, <Version: QGE__Power Sequencing fix__726__lalitb>]
>>>
ただし、ビューを使用して同じことを行うと:
from collabgrid.testmatrix.models import Testmatrix, Testcaseinfo, Product
from django.http import HttpResponse
from django.utils import simplejson
import json, pdb, datetime, reversion
class Execute:
model = None
delete_ids = []
def __init__(self, model):
self.model = model
if not reversion.is_registered(model):
reversion.register(model)
def update(self, n):
id = n.pk;
if len(self.model.objects.filter(pk=id)) > 0:
m= self.model.objects.get(pk=id)
if len(reversion.get_for_object(m)) == 1: # Update newly inserted element
reversion.get_for_object(m).delete() # reversion list only 1 long.
with reversion.create_revision():
m=n
m.save()
else: # Update existing element. reversion list will be at least 2 long
if len(reversion.get_for_object(m)) == 0: # Add self as first revision.
with reversion.create_revision():
m.save()
with reversion.create_revision(): # Add updates
m=n
m.save()
def insert(self, n):
with reversion.create_revision():
n.pk = None
n.save()
return n.pk
def delete(self, n):
id = n.pk
if len(self.model.objects.filter(pk=id)) > 0:
m=self.model.objects.get(pk=id)
with reversion.create_revision():
m.save()
delete_ids.append(id)
m.delete()
def discard(self, n):
id = n.pk
if len(self.model.objects.filter(pk=id)) > 0:
m=self.model.objects.get(pk=id)
rev=reversion.get_for_object(m)
if len(rev) == 0:
return
if len(rev) == 1: #insert operation, then delete
m.delete()
else: #update operation, then revert
rev[len(rev)-1].revert()
rev.delete()
if len(reversion.get_deleted(self.model).filter(object_id=id)) > 0:
reversion.get_deleted(self.model).get(object_id=id).revert()
def save(self, n):
id = n.pk
if len(self.model.objects.filter(pk=id)) > 0:
m=self.model.objects.get(pk=id)
m.save()
reversion.get_for_object(m).delete()
if len(reversion.get_deleted(self.model).filter(object_id=id)) > 0:
reversion.get_deleted(self.model).get(object_id=id).delete()
tm_execute=Execute(Testmatrix)
def update_sub_col(request):
print request
if request.method == 'POST':
ret = request.POST
tm_data = json.loads(request.POST['tm_data'])
for t in tm_data:
if(len(Testmatrix.objects.filter(pk=t['id'])) > 0):
tm = Testmatrix.objects.get(pk=t['id'])
if tm.os != t['sub_col']:
tm.os = t['sub_col']
print "BEFORE: ", reversion.get_for_object(tm) # List returns as empty []
tm_execute.update(tm)
print "AFTER: ",reversion.get_for_object(tm) # List returns as empty []
# but subsequent read has one
# revision entry.
json_response = {
'ret': 'success'
}
return HttpResponse(simplejson.dumps(json_response),mimetype='application/javascript')
後続の読み取りでは、リストが1つだけ長いことがわかります。
[<Version: QGE__Power Sequencing fix__726__lalitb>]
この時点で、モデルはすべての変更をコミットし、元に戻す方法はありません。どちらの場合も同じコードを使用しているため、なぜ違いがあるのか わかりません。
その後、pdbを使用してリビジョンリストの内容を確認しました
with reversion.create_revision():
m.save()
ビュー経由で更新機能を実行したときは空でしたが、シェルプロンプトを介してデバッグするとリビジョンエントリが正しく表示されました。