2016-11-23 54 views
0

我在django-models中有问题筛选。如何返回所有记录,但排除最后一项

我想返回特定animal的所有记录,但不包括基于最新的created_at值的最后一项,并按降序排序。

我有这个模型。

class Heat(models.Model): 

    # Fields 
    performer = models.CharField(max_length=25) 
    is_bred = models.BooleanField(default=False) 
    note = models.TextField(max_length=250, blank=True, null=True) 
    result = models.BooleanField(default=False) 

    # Relationship Fields 
    animal = models.ForeignKey(Animal, related_name='heats', on_delete=models.CASCADE) 

    created_at = models.DateTimeField(auto_now_add=True, editable=False) 
    last_updated = models.DateTimeField(auto_now=True, editable=False) 

我能够通过这些原始SQL脚本以达到期望的结果。但我想要一个Django方法。

SELECT 
    * 
FROM 
    heat 
WHERE 
    heat.created_at != (SELECT MAX((heat.created_at)) FROM heat) 
     AND heat.animal_id = '2' ORDER BY heat.created_at DESC; 

请帮助。

回答

3

这将是

Heat.objects.order_by("-created_at")[1:] 

对于特定的动物那么这将是:

Heat.objects.filter(animal_id=2).order_by("-created_at")[1:] 

其中[1:]queryset有一个普通的python slice语法和产生正确的SQL代码。 (在这种情况下,简单地删除第一个/最近创建的元素)

Upd:如@schwobaseggl提到的,在评论中,具有负向索引的切片在django查询集上不起作用。因此,对象首先是反向排序的。

+1

负面索引不适用于查询集! – schwobaseggl

+0

@艺术,感谢您的回复,但schwobaseggl是正确的,即使我将其更改为1仍然不是理想的结果。 –

+0

@schwobaseggl很高兴知道,谢谢 – Art

1

我刚刚将您的SQL查询转换为Django ORM代码。

首先,使用aggregation获取最大值created_at并执行exclude

from django.db.models import Max 

heat_objects = Heat.objects.filter(
    animal_id=2 
).exclude(
    created_at=Heat.objects.all().aggregate(Max('created_at'))['created_at__max'] 
) 
+0

这一个可能对未来有所帮助,你可以给一些解释吗? –

+0

我刚刚给代码添加了一些解释。 – anupsabraham

+0

谢谢,这可能会在未来有用。 –

1

获取最后一条记录:

obj= Heat.objects.all().order_by('-id')[0] 

制作查询:

query = Heat.objects.filter(animal_id=2).exclude(id=obj['id']).all() 
-1

的查询是:

Heat.objects.all().order_by('id')[1:] 

你也可以把你需要通过更换任何过滤器全部()