You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django ORM实现含外键的Group By查询?

Django ORM 实现指定SQL查询

首先假设你的Django模型定义如下(对应题目中的数据库表结构):

from django.db import models

class User(models.Model):
    id = models.AutoField(primary_key=True)
    display_name = models.CharField(max_length=255)
    # 其他业务字段...

class Tournament(models.Model):
    id = models.AutoField(primary_key=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='tournaments')
    start_date = models.DateTimeField()
    # 其他业务字段...

你可以通过两种方式实现目标SQL:

方式一:从User模型出发查询

利用User模型的反向关联(tournaments是外键的related_name)过滤赛事时间,再统计每个用户的赛事数量:

from django.db.models import Count
from django.utils import timezone

# 执行查询
query_result = User.objects.filter(
    tournaments__start_date__date__gt=timezone.date(2022, 7, 1)
).annotate(
    tournament_count=Count('tournaments')
).values('id', 'display_name', 'tournament_count')

方式二:从Tournament模型出发查询

直接从赛事表过滤时间,按用户字段分组后统计数量,更贴近原SQL的逻辑:

from django.db.models import Count
from django.utils import timezone

# 执行查询
query_result = Tournament.objects.filter(
    start_date__date__gt=timezone.date(2022, 7, 1)
).values(
    'user__id', 'user__display_name'
).annotate(
    tournament_count=Count('id')
).order_by('user__id', 'user__display_name')

注意事项:

  • 如果Tournament模型中外键的related_name未指定(默认是tournament_set),需要把方式一中的tournaments替换为tournament_set。
  • 如果start_date字段是DateField而非DateTimeField,则去掉查询中的__date,直接写start_date__gt=timezone.date(2022, 7, 1)。

内容的提问来源于stack exchange,提问作者pineforest22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:35:25