Django 上 Count 函数的不同行为
Posted
技术标签:
【中文标题】Django 上 Count 函数的不同行为【英文标题】:Different behaviour of Count function on Django 【发布时间】:2021-08-17 03:59:32 【问题描述】: 我有一个非常奇怪的情况,如果将 Count() 应用于通过 id 或其他过滤器过滤的模型,它的行为会有所不同。 我有这些模型:class Segment(models.Model):
is_completed = models.BooleanField(default=False)
class Waypoint(models.Model):
is_visited = models.BooleanField("is visited", default=False)
segment = models.ForeignKey("Segment", on_delete=models.PROTECT, related_name="waypoints", null=True, default=None)
假设我们有两个尚未访问过的航路点,都与同一航段相关。
我在查询集中有这些航点之一,称之为wp
。现在,如果我执行:
to_visit_filter = Q(waypoints__is_visited=False)
seg = Segment.objects.filter(waypoints__in=wp, is_completed=False).annotate(
wp_to_visit=Count('waypoints', filter=to_visit_filter))
print(seg.first().wp_to_visit) // 1
相反,如果我这样做:
to_visit_filter = Q(waypoints__is_visited=False)
segm_id = [w.segment.id for w in wp]
seg = Segment.objects.filter(id__in=segm_id, is_completed=False).annotate(
wp_to_visit=Count('waypoints', filter=to_visit_filter))
print(seg.first().wp_to_visit) // 2
在这两种情况下seg.first()
都给出了相同的对象实例,但是要访问的路点数量不同。为什么?
【问题讨论】:
【参考方案1】:在您的第一个查询中,您对 航点 (waypoints__in=wp
) 执行过滤,因此将航点限制为选定的Waypoint
。此过滤导致带有Waypoint
模型和WHERE 子句的LEFT OUTER JOIN。接下来,您使用waypoints
上的Count
对航路点执行聚合和分组。此注释将使用与上一次调用 filter
相同的连接,因此显然您的计数结果为 1。
接下来在您的第二个查询中,您不是过滤航点,而是过滤段 @987654327@ 本身,因此没有对航点进行过滤,您的查询为您提供 2 的计数。
【讨论】:
以上是关于Django 上 Count 函数的不同行为的主要内容,如果未能解决你的问题,请参考以下文章
在过滤损坏的记录字段时,Spark 的 .count() 函数与数据帧的内容不同
Oracle 上 SELECT * 和 SELECT COUNT(*) 之间的结果大小不同
django-filter + DRF ModelView为不同的字段设置不同的行为