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

如何使用Django ORM编写查询,获取每个Ticket关联的最新TicketDetails记录及全量字段

解决Django中关联获取最新关联记录的问题

嘿,我来帮你搞定这个Django查询的问题!你需要获取Ticket表的所有字段,同时关联每个Ticket对应的最新一条TicketDetails记录,对吧?下面我给你两种靠谱的实现方式,都是基于Django ORM的,也可以用原生SQL兜底。

首先先确认下你的Django模型结构(根据你给出的表结构转换):

from django.db import models

class Ticket(models.Model):
    name = models.CharField(max_length=100)
    type = models.CharField(max_length=100)
    user = models.CharField(max_length=100)

class TicketDetails(models.Model):
    ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, related_name='details')
    message = models.TextField()
    created_time = models.DateTimeField()

方法一:用Subquery和OuterRef(推荐的ORM方式)

这种方式完全用Django的ORM实现,不需要写原生SQL,兼容性更好。

首先导入需要的模块:

from django.db.models import OuterRef, Subquery, Max

然后分三步构建查询:

  1. 先找到每个Ticket对应的最新created_time
  2. 根据这个时间找到对应的TicketDetails记录
  3. 把这些字段关联到Ticket的查询结果中

完整代码:

# 子查询1:获取每个ticket对应的最新消息时间
latest_created_time = TicketDetails.objects.filter(
    ticket=OuterRef('pk')
).values('ticket').annotate(
    latest_time=Max('created_time')
).values('latest_time')

# 子查询2:根据最新时间,获取对应的message和created_time
latest_details = TicketDetails.objects.filter(
    ticket=OuterRef('pk'),
    created_time=Subquery(latest_created_time)
).values('message', 'created_time')

# 最终查询:关联Ticket表,获取所有需要的字段
result = Ticket.objects.annotate(
    message=Subquery(latest_details.values('message')[:1]),
    created_time=Subquery(latest_details.values('created_time')[:1])
).values('id', 'name', 'type', 'user', 'message', 'created_time')

特殊情况处理

如果存在同一个ticket_id下有多条时间完全相同的消息,上面的方法会返回多条结果。如果你想确保每个Ticket只返回一条,可以改成按created_time倒序+id倒序取第一条:

# 直接按时间和id倒序,取第一条最新记录
latest_details = TicketDetails.objects.filter(
    ticket=OuterRef('pk')
).order_by('-created_time', '-id').values('message', 'created_time')[:1]

result = Ticket.objects.annotate(
    message=Subquery(latest_details.values('message')),
    created_time=Subquery(latest_details.values('created_time'))
).values('id', 'name', 'type', 'user', 'message', 'created_time')

方法二:原生SQL查询

如果你更熟悉SQL语法,也可以直接用原生SQL来实现:

result = Ticket.objects.raw('''
    SELECT t.id, t.name, t.type, t.user, td.message, td.created_time
    FROM ticket t
    JOIN ticket_details td ON t.id = td.ticket_id
    WHERE (td.ticket_id, td.created_time) IN (
        SELECT ticket_id, MAX(created_time)
        FROM ticket_details
        GROUP BY ticket_id
    )
''')

这个SQL的思路是:先通过子查询分组找到每个ticket_id对应的最新时间,再关联筛选出对应的消息记录,最后和Ticket表关联返回所有字段。

结果验证

运行上面的代码后,result里的每条数据就对应一个Ticket加上它的最新一条TicketDetails记录,和你期望的输出完全一致~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 19:42:55