Django获取与查询匹配的最新对象

时间:2017-05-22 14:51:26

标签: django python-3.x django-queryset

让我们说我有一个类型的模型:

class Related(models.Model):
    ... stuff ....

class Example(models.Model):
    field1 = models.ForeignKey(Related, on_delete=models.CASCADE, related_name='+')
    field2 = models.ForeignKey(Related, on_delete=models.CASCADE, related_name='+')
    created = models.DateTimeField(default=timezone.now)
    ... more fields

我想要做的是为每个固定的field1和field2选择最新的示例。我想从Example中选择所有字段。假设Example中的条目数可能是数百万。

可以执行此任务的示例sql查询(假设应用程序名称' test'):

select * from test_example as e 
where not exists (
    select id 
    from test_example as e2 
    where e2.field1_id = e.field1_id 
        and e2.field2_id = e.field2_id 
        and e2.created > e.created)

有没有什么方法可以表达与QuerySet API类似的东西?到目前为止,我发现的唯一解决方案是运行原始SQL,我真的想避免这种情况。

2 个答案:

答案 0 :(得分:0)

latest = Example.objects.filter(field1="foo", field2="bar").latest('created')

更多信息: https://docs.djangoproject.com/en/dev/ref/models/querysets/#latest

编辑:以下答案最有可能是您所追求的:

Django - remove duplicate objects where there is more than one field to compare

答案 1 :(得分:0)

我发现的解决方案仅适用于postresql,但幸运的是我使用的是postgresql。

首先让我们开始解释postgresql中存在的特殊子句 - DISTINCT ON。您可以阅读使用它的示例here。简而言之,对于我的案例,postgresql中的有效查询将是:

SELECT DISTINCT ON (e.field1_id, e.field2_id) e.* 
       FROM Example as e 
       ORDER BY e.created DESC

上面的实质是我只能使用所选字段的一个子集来计算DISTINCT。

更好的是,事实证明django的QuerySet也支持distinct。更具体地说(链接引用):

  

仅在PostgreSQL上,您可以传递位置参数(*字段)   命令指定DISTINCT应该应该的字段的名称   应用。这转换为SELECT DISTINCT ON SQL查询。

使用这个我可以在django中写下以下内容:

Example.objects.all().order_by('field1', 'field2', '-created').distinct(
        'field1', 'field2)

重要的是要注意,distinct字段应该是order_by子句中列出的第一个字段,它们应该是相同的顺序。

我希望这个答案可以帮助其他人解决类似的问题。