The problem is that the cascaded deletions are performed before the requested object is deleted, hence when you queried the DB ( A.objects.get(id=instance.a.id)
) the related a
instance is present there.
(的问题是,当你查询的DB(级联缺失所请求的对象被删除之前进行的,因此A.objects.get(id=instance.a.id)
相关的a
实例是目前。)
instance.a
can even show a cached result so there's no way it would show otherwise. (instance.a
甚至可以显示缓存的结果,因此不可能显示否则。)
So while deleting a B
model instance, the related A
instance will always be existent (if actually there's one).
(因此,在删除B
模型实例时,相关的A
实例将始终存在(如果实际存在)。)
Hence, from the B
model post_delete
signal receiver, you can get the related A
instance and check if the related B
actually exists from DB (there's no way to avoid the DB here to get the actual picture underneath): (因此,从B
模型post_delete
信号接收器中,您可以获取相关的A
实例,并从DB中检查相关的B
确实存在(无法避免DB在这里获取下面的实际图片):)
@receiver(post_delete, sender=B)
def post_delete_b(sender, instance, *args, **kwargs):
try:
a = instance.a
except AttributeError:
return
try:
a._state.fields_cache = {}
except AttributeError:
pass
try:
a.b # one extra query
except AttributeError:
# This is cascaded delete
return
a.delete()
We also need to make sure we're not getting any cached result by making a._state.fields_cache
empty.
(我们还需要通过将a._state.fields_cache
空来确保没有得到任何缓存结果。)
The fields_cache
(which is actually a descriptor that returns a dict
upon first access) is used by the ReverseOneToOneDescriptor
(accessor to the related object on the opposite side of a one-to-one) to cache the related field name-value. (所述fields_cache
(这实际上是一个返回的描述符dict
在第一接入)用于由ReverseOneToOneDescriptor
(存取器上的一对之一的相对侧上的相关对象)来缓存相关领域的名称-值。)
FWIW, the same is done on the forward side of the relationship by the ForwardOneToOneDescriptor
accessor. (FWIW, ForwardOneToOneDescriptor
访问器在关系的前端执行相同的操作。)
Edit based on comment:
(根据评论进行编辑:)
If you're using this function for multiple senders' post_delete
, you can dynamically get the related attribute via getattr
:
(如果将此功能用于多个发件人的post_delete
,则可以通过getattr
动态获取相关属性:)
getattr(a, sender.a.field.related_query_name())
this does the same as ab
above but allows us to get attribute dynamically via name, so this would result in exactly similar query as you can imagine.
(这和上面的ab
,但是允许我们通过名称动态获取属性,因此这将导致您完全可以想象的类似查询。)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…