如何使用另一个查询作为可能值通过 GenericForeignKey-Field 过滤查询?

Posted

技术标签:

【中文标题】如何使用另一个查询作为可能值通过 GenericForeignKey-Field 过滤查询?【英文标题】:How can I filter a query by a GenericForeignKey-Field using another query as possible values? 【发布时间】:2015-03-03 17:54:36 【问题描述】:

我有两个应用程序:一个简单的消息应用程序和一个用于评分的应用程序。

这些点是只有一个通用外键的模型,并且根据它们的存在数量,有一个值分配给我想要的一切。

class Point(models.Model):
  content_type = models.ForeignKey(ContentType)
  object_id = models.PositiveIntegerField()
  content_object = GenericForeignKey('content_type', 'object_id')
  user = models.ForeignKey('auth.User')

现在我在努力思考如何解决这个问题:我有一个清单,例如消息:

class Message(models.Model):
  subject = models.CharField(max-length=255)
  body = models.TextField()


things = Point.objects.all()

所以现在的目标是按分配给每个对象的点数对其进行排序。这将很容易使用相关的查询名称。但是我的消息应用程序将完全依赖于积分应用程序。

这就是为什么我宁愿只使用模板标签来解决这个问题。我正在考虑将“事物”传递给模板标签,然后按点对这个查询集进行排序。它应该看起来像这样:

@register.simple_tag()
def get_points_for_query(q):
  points = Point.objects.filter(content_object__in=q).prefetch_related('content_obj').order_by('pk')
  return points

这当然行不通,因为通用外键不能与“__in”一起使用。但是如果我遍历查询集并调用:

for obj in q:
  ct = ContentType.objects.get_for_model(obj)

这会给我的服务器带来很多工作。有没有办法为查询获取一次内容类型?我只打算对只查询单一类型内容的标签进行查询。或者有没有更好的方法来解决这个问题而不使这些应用相互依赖?

感谢您的帮助。

【问题讨论】:

我认为您对耦合的担忧过多而对内聚的担忧不够。将Point 抽象化,然后将MessagePoint 类与Message 的FK 相结合。通用关系,也称为Polymorphic Associations,很少是一件好事。看看SQL Antipatterns: Avoiding the Pitfalls of Database Programming 【参考方案1】:

您可以获取查询集的模型,然后针对该特定内容类型过滤 Point

@register.simple_tag()
def get_points_for_query(q):
    ct = ContentType.objects.get_for_model(q.model)
    return Point.objects.filter(content_type=ct, object_id__in=q) \
                        .prefetch_related('content_obj').order_by('pk')

我不确定object_id__in=q 子句。如果它不起作用,请尝试:

object_id__in=q.values_list('id', flat=True)

这应该可以正常工作。

【讨论】:

以上是关于如何使用另一个查询作为可能值通过 GenericForeignKey-Field 过滤查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据连接表值选择“假”列/值?

如何使用 Apollo GraphQL 查询结果作为另一个查询的输入?又名:请求链

如何在另一个 Prometheus 查询中引用查询值

MYSQL - 如何在一个条件的值与另一个条件的值匹配的情况下运行查询?

怎样将数组作为Sql中IN的查询条件

如何避免Kotlin暴露的N + 1查询问题。 (通过DAO的Reference.id.value字段获取值时)