首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >查找某个类中与其他对象没有任何活动链接的所有对象。

查找某个类中与其他对象没有任何活动链接的所有对象。
EN

Stack Overflow用户
提问于 2022-11-16 22:08:29
回答 1查看 23关注 0票数 1

我有一个类A,它在许多其他类中用作外键。

代码语言:javascript
运行
复制
class A(models.Model):
  pass

class B(models.Model):
  a: A = ForeignKey(A)

class C(models.Model):
  other_name: A = ForeignKey(A)

现在,我有了一个数据库,其中包含一个庞大的A对象表和许多类,比如BC,它们引用了A (比方说可能有几十个)。在这个表中,有许多对象(100k+),我想清除所有没有被其他对象使用外键主动引用的对象。例如,类object 1 of A不被类BC引用。

我该怎么做?我已经想出了以下代码:

代码语言:javascript
运行
复制
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()

这给我留下了几个问题:

如果我不知道类和字段的完整列表(因为它是一个很大的组),那么

  • 怎么办?
  • 对于一个有许多无关对象的大表(比如95%)来说,这是最有效的方法吗?我想我可以对它进行很多优化。
EN

回答 1

Stack Overflow用户

发布于 2022-11-16 22:23:40

您可以通过以下方式进行过滤:

代码语言:javascript
运行
复制
A.objects.filter(b=None, c=None).delete()

这将进行适当的连接,从而确定单个查询中的项,而不必从数据库中获取所有其他模型记录。

但是无论如何,这将是昂贵的,因为触发器是由Django完成的,它将“收集”所有的A对象。

如果您不知道什么是引用A,则可以使用模型的元数据,因此:

代码语言:javascript
运行
复制
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模型为目标的其他模型中查找所有的AOneToOneField,然后在NULL上进行LEFT OUTER JOIN和筛选,然后删除这些模型。

不过,我建议您首先检查A.objects.filter(**fields),并确保您没有删除任何仍然必要的项目。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74467841

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档