Django query select distinct by field pairs

cro*_*jer 8 python django django-queryset

我有"提交"字段,其中包含用户和问题.如何获得SQL搜索结果,该结果将为每个用户问题对提供仅一个结果的列表?

模型是这样的:

class Problem(models.Model):
    title = models.CharField('Title', max_length = 100)
    question = models.TextField('Question')

class Submission(models.Model):
    user = models.ForeignKey(User)
    problem = models.ForeignKey(Problem)
    solution = models.CharKey()
    time = models.DateTimeField('Time', auto_now_add=True)
Run Code Online (Sandbox Code Playgroud)

Tom*_*zuk 13

试试这个:

distinct_users_problems = Submission.objects.all().values("user", "problem").distinct()
Run Code Online (Sandbox Code Playgroud)

它会给你一个像这样的dicts列表:

[{'problem': 1, 'user': 1}, {'problem': 2, 'user': 1}, {'problem': 3, 'user': 1}]
Run Code Online (Sandbox Code Playgroud)

包含所有不同的对.

它实际上导致您通常的SELECT DISTINCT SQL查询.


Man*_*dan 3

更新2

(阅读OP的评论后)我建议添加一个新模型来跟踪最新的提交。叫它LatestSubmission

class LatestSubmission(models.Model):
    user = models.ForeignKey(User)     
    problem = models.ForeignKey(Problem)
    submission = models.ForeignKey(Submission)
Run Code Online (Sandbox Code Playgroud)

然后你可以

  1. 每次用户发布问题的新解决方案时覆盖Submission.save()以创建/更新条目LatestSubmission
  2. 将执行相同操作的函数附加到合适的信号

这样,LatestSubmission每个问题-用户-提交组合将包含一行,指向每个用户对该问题的最新提交。一旦你完成了这个,你就可以触发一个查询:

LatestSubmission.objects.all().order_by('problem')
Run Code Online (Sandbox Code Playgroud)

更新

由于OP已经发布了示例代码,现在可以将解决方案更改如下:

for user in User.objects.all(): # Get all users
    user.submission_set.latest('time') # Pick the latest submission based on time.
Run Code Online (Sandbox Code Playgroud)

原答案

如果没有任何基于日期/时间的标准来确定“较旧”或“较新”,您可以使用主键 ( id) 来Submission“忽略旧的”。

for user in User.objects.all(): # Get all users
    user.submission_set.latest('id') # Pick the latest submission by each user.
Run Code Online (Sandbox Code Playgroud)