Django queryset - 基于外键的组并获得计数

时间:2016-01-10 11:45:43

标签: django django-models

我有3张表如下:

class Bike:
 name = CharField(...)
 cc_range = IntField(...)

class Item:
  bike_number = CharField(...)
  bike = ForeignKey(Bike)

class Booking:
  start_time = DateTimeField(...)
  end_time = DateTimeField(...)
  item = ForeignKey(Item, related_name='bookings')

我想获得一段时间内未预订的所有自行车清单(例如,[" 2016-01-09"," 2016-01-11&#34] ;])带有项目计数。

例如,假设有两辆自行车b1,b2,项目为i11,i12和i21,i22。如果i21参与预订(比如[" 2016-01-10"," 2016-01-12"])那么我想要像

这样的东西
{"b1": 2, "b2": 1}


我有相关的项目
Item.objects
.exclude(bookings__booking_time__range=booking_period)
.exclude(bookings__completion_time__range=booking_period)

但我无法将它们分组。


我也尝试过:

Bike.objects
.exclude(item__bookings__booking_time__range=booking_period)
.exclude(item__bookings__completion_time__range=booking_period)
.annotate(items_count=Count('item')

但如果预订了任何一件物品,它就会移走整辆自行车。


我似乎完全陷入困境。我宁愿这样做而不使用for循环。 django文档似乎也没有帮助我(这是罕见的)。对于我想要解决的问题类型,我的模型架构是否存在问题。或者我错过了什么。任何帮助将不胜感激。

提前致谢!!

1 个答案:

答案 0 :(得分:0)

from django.db.models import Q, Count, Case, When, Value, BooleanField

bikes = models.Bike.objects.annotate(
        booked=Case(
         When(Q(item__bookings__start_time__lte=booking_period[1]) & Q(item__bookings__end_time__gte=booking_period[0]),
              then=Value(True)),
         default=Value(False),
         output_field=BooleanField(),
     )).filter(booked=False).annotate(item_count=Count('item'))

请阅读有关条件表达式的documentation