Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在django中实现计数注释的交叉连接_Python_Django_Join_Orm_Annotations - Fatal编程技术网

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的情况下进行交叉连接。我可以给你两个想法,为你指明正确的方向:

  • 查询和python循环的组合

    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
    
  • 更难的是,我没有一个解决方案是使用过滤器、排除和并集的组合。我只使用了3个表(两个父表和一个子链接表),其中包括4个用户。因此,我只能提供逻辑,不能提供示例

    # 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的情况下进行交叉连接。我可以给你两个想法,为你指明正确的方向:

  • 查询和python循环的组合

    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
    
  • 更难的是,我没有一个解决方案是使用过滤器、排除和并集的组合。我只使用了3个表(两个父表和一个子链接表),其中包括4个用户。因此,我只能提供逻辑,不能提供示例

    # 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