私は1対多の関係にあり、多側の最後の参照オブジェクトが削除された後、片側を自動的に削除したいと思います。つまり、ガベージコレクションを実行したい、または一種の逆カスケード操作を実行したいのです。
私はDjangoのpost_deleteシグナルを使用してこれを解決しようとしました。これが私がやろうとしていることの簡単な例です:
models.py
class Bar(models.Model):
j = models.IntegerField()
# implicit foo_set
class Foo(models.Model):
i = models.IntegerField()
bar = models.ForeignKey(Bar)
def garbage_collect(sender, instance, **kwargs):
# Bar should be deleted after the last Foo.
if instance.bar.foo_set.count() == 0:
instance.bar.delete()
post_delete.connect(garbage_collect, Foo)
これは、を使用すると機能しますModel.delete
が、使用するQuerySet.delete
とひどく壊れます。
tests.py
class TestGarbageCollect(TestCase):
# Bar(j=1)
# Foo(bar=bar, i=1)
# Foo(bar=bar, i=2)
# Foo(bar=bar, i=3)
fixtures = ['db.json']
def test_separate_post_delete(self):
for foo in Foo.objects.all():
foo.delete()
self.assertEqual(Foo.objects.count(), 0)
self.assertEqual(Bar.objects.count(), 0)
これは問題なく機能します。
tests.pyの続き
def test_queryset_post_delete(self):
Foo.objects.all().delete()
self.assertEqual(Foo.objects.count(), 0)
self.assertEqual(Bar.objects.count(), 0)
Djangoのドキュメントに記載されているように、これは信号が2回目に発信されたときに中断し、QuerySet.delete
即座に適用されinstance.bar.foo_set.count() == 0
、信号が最初に発信されたときにすでに当てはまります。引き続きドキュメントを読んでいると、削除されたすべてのオブジェクトに対してシグナルQuerySet.delete
が送信され、削除された後に呼び出されます。post_delete
garbage_collect
Bar
質問に:
- 1対多の関係の片側をガベージコレクションするより良い方法はありますか?
- そうでない場合、QuerySet.deleteを使用できるようにするには何を変更する必要がありますか?