gpt4 book ai didi

python - Django CASCADE 和 post_delete 交互

转载 作者:行者123 更新时间:2023-12-01 06:49:46 24 4
gpt4 key购买 nike

我有以下模型:

class A():
foriegn_id1 = models.CharField # ref to a database not managed by django
foriegn_id2 = models.CharField

class B():
a = models.OneToOneField(A, on_delete=models.CASCADE)

所以我希望在删除 B 时也删除 A:

@receiver(post_delete, sender=B)
def post_delete_b(sender, instance, *args, **kwargs):
if instance.a:
instance.a.delete()

在删除 A 时,我想从非托管数据库中删除对象:

@receiver(post_delete, sender=A)
def post_delete_b(sender, instance, *args, **kwargs):
if instance.foriegn_id1:
delete_foriegn_obj_1(instance.foriegn_id1)
if instance.foriegn_id2:
delete_foriegn_obj_2(instance.foriegn_id2)

现在,如果我删除对象 B,它就可以正常工作。但是如果我删除了obj A,那么obj B就会被级联删除,然后它会发出post_delete信号,从而再次触发A的删除。 Django 知道如何管理它,因此它可以正常工作,直到到达 delete_foriegn_obj,然后调用两次并在第二次尝试时返回失败。

我考虑过验证该对象是否存在于 delete_foriegn_obj 中,但它又增加了 3 个对数据库的调用。

所以问题是:有没有办法在 post_delete_b 期间知道对象 a 已被删除?instance.aA.objects.get(id=instance.a.id) 都返回对象(我猜 Django 会缓存数据库更新,直到完成所有已完成删除)。

最佳答案

问题是级联删除是在删除请求的对象之前执行的,因此当您查询数据库时(A.objects.get(id=instance.a.id) )相关的a实例存在于那里。 instance.a 甚至可以显示缓存的结果,因此不可能以其他方式显示。

因此,在删除 B 模型实例时,相关的 A 实例将始终存在(如果确实存在)。因此,从 B 模型 post_delete 信号接收器中,您可以获取相关的 A 实例,并检查相关的 B 是否存在> 实际上存在于数据库中(没有办法避开数据库来获取下面的实际图片):

@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()

我们还需要通过将 a._state.fields_cache 清空来确保我们不会获得任何缓存结果。 fields_cache(实际上是一个描述符,在第一次访问时返回一个dict)由ReverseOneToOneDescriptor(对相关对象的访问器)使用一对一的另一侧)来缓存相关字段名称-值。 FWIW,ForwardOneToOneDescriptor 访问器在关系的前向一侧完成了相同的操作。

<小时/>

根据评论进行编辑:

如果您将此功能用于多个发件人的 post_delete,您可以通过 getattr 动态获取相关属性:

getattr(a, sender.a.field.related_query_name())

这与上面的 a.b 相同,但允许我们通过名称动态获取属性,因此这将导致与您想象的完全相同的查询。

关于python - Django CASCADE 和 post_delete 交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59074908/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com