Python 如何在django中实现计数注释的交叉连接
我提出了我的问题的简化版本。我有场地、时间段、用户和预订,如下面的模型描述所示。所有场馆的时隙都是通用的,用户可以在一个场馆预订一个时隙,直到达到场馆容量为止Python 如何在django中实现计数注释的交叉连接,python,django,join,orm,annotations,Python,Django,Join,Orm,Annotations,我提出了我的问题的简化版本。我有场地、时间段、用户和预订,如下面的模型描述所示。所有场馆的时隙都是通用的,用户可以在一个场馆预订一个时隙,直到达到场馆容量为止 class Venue(models.Model): name = models.Charfield(max_length=200) capacity = models.PositiveIntegerField(default=0) class TimeSlot(models.Model): start_t
class Venue(models.Model):
name = models.Charfield(max_length=200)
capacity = models.PositiveIntegerField(default=0)
class TimeSlot(models.Model):
start_time = models.TimeField()
end_time = models.TimeField()
class Booking(models.Model):
user = models.ForeignKey(User)
time_slot = models.ForeignKey(TimeSlot)
venue = models.ForeignKey(Venue)
现在,我希望尽可能高效地获取所有可能的场馆和时间段组合,并注释每个组合的预订数量,包括预订数量为0的情况
我已经设法在原始SQL中通过在场地和时间段表上使用交叉连接实现了这一点。与以下内容有关的内容。然而,尽管进行了详尽的搜索,我们仍未能找到与django类似的产品
SELECT venue.name, timeslot.start_time, timeslot.end_time, count(booking.id)
FROM myapp_venue as venue
CROSS JOIN myapp_timeslot as timeslot
LEFT JOIN myapp_booking as booking on booking.time_slot_id = timeslot.id
GROUP BY venue.name, timeslot.start_time, timeslot.end_time
我还能够对查询进行注释,以检索该组合的预订确实存在的预订数量。但那些预订量为0的组合将被排除在外。例如:
qs = Booking.objects.all().values(
venue=F('venue__name'),
start_time=F('time_slot__start_time'),
end_time=F('time_slot__end_time')
).annotate(bookings=Count('id')) \
.order_by('venue', 'start_time', 'end_time')
如何使用django ORM实现交叉连接查询的效果?我不相信django有能力在不恢复原始SQL的情况下进行交叉连接。我可以给你两个想法,为你指明正确的方向:
venues = Venue.objects.all()
time_slots = TimeSlot.objects.all()
qs = ** your customer query above **
# Loop through both querysets, to create a master list.
venue_time_slots = []
for venue in venues:
for time_slot in time_slots:
venue_time_slots.append(venue.name, time_slot.start_time, time_slot.end_time, 0)
# Loop through master list and then compare to custom qs to update the count.
for venue_time in venue_time_slots:
for vt in qs:
# Check if venue and time found.
if venue_time[0] == qs.venue and venue_time[1] == qs.start_time:
venue_time[3] += qs.bookings
break
# Get all results that exist in table using .filter().
first_query.filter()
# Get all results that do not exist by using .exclude().
# You can use your results from the first query to exclude also, but
# would need to create an interim list.
exclude_ids = [fq_row.id for fq_row in first_query]
second_query.exclude(id__in=exclude_ids)
# Combine both queries
query = first_query.union(second_query)
return query
我不相信Django有能力在不恢复原始SQL的情况下进行交叉连接。我可以给你两个想法,为你指明正确的方向:
venues = Venue.objects.all()
time_slots = TimeSlot.objects.all()
qs = ** your customer query above **
# Loop through both querysets, to create a master list.
venue_time_slots = []
for venue in venues:
for time_slot in time_slots:
venue_time_slots.append(venue.name, time_slot.start_time, time_slot.end_time, 0)
# Loop through master list and then compare to custom qs to update the count.
for venue_time in venue_time_slots:
for vt in qs:
# Check if venue and time found.
if venue_time[0] == qs.venue and venue_time[1] == qs.start_time:
venue_time[3] += qs.bookings
break
# Get all results that exist in table using .filter().
first_query.filter()
# Get all results that do not exist by using .exclude().
# You can use your results from the first query to exclude also, but
# would need to create an interim list.
exclude_ids = [fq_row.id for fq_row in first_query]
second_query.exclude(id__in=exclude_ids)
# Combine both queries
query = first_query.union(second_query)
return query