我有一个类A
,它在许多其他类中用作外键。
class A(models.Model):
pass
class B(models.Model):
a: A = ForeignKey(A)
class C(models.Model):
other_name: A = ForeignKey(A)
现在,我有了一个数据库,其中包含一个庞大的A
对象表和许多类,比如B
和C
,它们引用了A
(比方说可能有几十个)。在这个表中,有许多对象(100k+),我想清除所有没有被其他对象使用外键主动引用的对象。例如,类object 1
of A
不被类B
和C
引用。
我该怎么做?我已经想出了以下代码:
a_list: list = list()
classes: list[tuple] = [(B, "a"), (C, "other_name")]
for cl, field in classes:
field_object: Field = cl._meta.get_field(field)
for obj in cl.objects.all():
a: A = field_object.value_from_object(obj)
a_list.append(a)
to_remove: list[A] = [a for a in A.objects.all() if a not in a_list]
for a in to_remove():
a.remove()
这给我留下了几个问题:
如果我不知道类和字段的完整列表(因为它是一个很大的组),那么
发布于 2022-11-16 22:23:40
您可以通过以下方式进行过滤:
A.objects.filter(b=None, c=None).delete()
这将进行适当的连接,从而确定单个查询中的项,而不必从数据库中获取所有其他模型记录。
但是无论如何,这将是昂贵的,因为触发器是由Django完成的,它将“收集”所有的A
对象。
如果您不知道什么是引用A
,则可以使用模型的元数据,因此:
from django.db.models.fields.reverse_related import OneToOneRel
fields = {
f.related_query_name: None
for f in A._meta.get_fields()
if isinstance(f, ManyToOneRel)
}
A.objects.filter(**fields).delete()
这将从(直接)以ForeignKey
模型为目标的其他模型中查找所有的A
和OneToOneField
,然后在NULL
上进行LEFT OUTER JOIN
和筛选,然后删除这些模型。
不过,我建议您首先检查A.objects.filter(**fields)
,并确保您没有删除任何仍然必要的项目。
https://stackoverflow.com/questions/74467841
复制相似问题