Django multiple exists()聚合

时间:2016-08-22 12:16:58

标签: django case aggregate models exists

class Order(models.Model):
      # Some fields..
      status = models.IntegerField()
      user = models.ForeignKey(User)

状态字段可以得到四个值:1,2,3,4

我想根据以下内容执行一个查询,该查询将返回带有指示符的单个行(元组):

if in the queryset there is a row with status=1, return 1  
elif there's row with status=3, return 3  
elif there's row with status=4, return 4  
elif there's row with status=2, return 2 

在此优先级中(即,按此顺序,类似于switch-case的工作原理)。 我查询它们以便特定用户显示某些状态消息。所以它应该有点像这样:

Order.objects.filter(user=request.user) # ...? .aggregate() maybe ?

我只需要指标,而不是任何订单对象 我认为在数据库级别它会像Case那样,但我无法使用django。

编辑:为了更好地解释,我可以这样做

if Order.objects.filter(user=request.user, status=1).exists():
   return 1
elif Order.objects.filter(user=request.user, status=3).exists():
   return 3
elif Order.objects.filter(user=request.user, status=4).exists():
   return 4
elif Order.objects.filter(user=request.user, status=2).exists():
   return 2

但显然我想避免做4次查询..

3 个答案:

答案 0 :(得分:2)

Order.objects.annotate(order_status=models.Case(
     models.When(status=1, then=0),
     models.When(status=3, then=1),
     models.When(status=4, then=2),
     models.When(status=2, then=3),
     default=models.F('status'),
     output_field=models.IntegerField(),
),).aggregate(models.Min('order_status'))

需要一些dict来映射状态

答案 1 :(得分:1)

order_statuses = Order.objects.filter(user=request.user).values_list('status', flat=True)

这将返回状态列表。现在您可以检查:

if 1 in order_statuses:
    return 1
elif 2 in order_statuses:
    return 3
elif 3 in order_statuses:
    return 4
elif 4 in order_statuses:
    return 2

这样你就可以在Django服务器上进行计算,而不是增加数据库的额外负载。

答案 2 :(得分:0)

你可以这样做:

# This will return a value of None, if no matching Order object exists,
# or the lowest status that exists:
return Order.objects.filter(
    user=request.user
).order_by(
   'status'
).values_list(
    'status', flat=True
).first()