Каскадное удаление в Django + сбор удаленных данных
У меня есть модели Django 2.2:
class A(models.Model):
pass
class B(models.Model):
a = models.ForeignKey(A, on_delete=models.CASCADE)
class C(models.Model):
b = models.ForeignKey(B, on_delete=models.CASCADE)
url = models.URLField(...)
def do_something(set_of_urls):
...
What I want is to do_something
with all url
values for which C
instance being deleted, but I need to do it at once.
In other words, when a.delete()
cascades, deleting all of its B
children, which in turn delete all of their C
children, I want to call
do_something({c.url for c in C.objects.filter(b__a_id=a.pk)})
Но я также хочу иметь возможность сделать b.delete()
, что в результате приведет к
do_something({c.url for c in C.objects.filter(b_id=b.pk)})
And same for c.delete()
(which would just do do_something({c.url})
).
Далее, удаление менеджеров отношений должно вести себя аналогичным образом:
A.objects.filter(...).delete()
would ideally calldo_something
for each deleted instance ofA
(so, not all URLs at once, but one call per each delete object). If grouping is problematic to implement, I could do withdo_something
for URLs of all affected instances ofC
. But I must avoid callingdo_something
for each affectedC
-child separately.B.objects.filter(...). delete()
would calldo_something
for all URLs belonging to children of those deleted instances (filter
will always ensure that all deleted instances ofB
belong to the same instance ofA
, so no grouping is needed).C.objects.filter(...).delete()
would calldo_something
for all URLs belonging to deleted instances (again, no grouping is needed).
I thought of using pre_delete
or post_delete
signals, but these seem to work bottom-up, meaning that individual processing of URLs in grandchildren of a
will be done before we get to pre_delete
of A
, which means that do_something
would get called by each C
-grandchild of a
instead of all of them in bulk.
Есть ли хороший способ сделать это?
Побочный вопрос для комментариев: документирован ли порядок вызовов сигналов в случае каскадного удаления где-нибудь в документации Django или где-нибудь еще? Я не смог его найти.