Как отфильтровать с помощью метода поиска «in or range» и убедиться, что какой-либо элемент в списке недоступен, а затем вернуть пустой набор запросов - PullRequest
0 голосов
/ 05 апреля 2020

Мой фрагмент кода:

boards_qs = BoardRate.objects.filter(
        Q(room_status="OP") &
        Q(hotel_log__date__range=[check_in_date, check_out_date]) &
        Q(hotel_log__hotel__pk__in=hotel_id_list) &
        Q(hotel_log__room_to_sell__gte=F("hotel_log__room_sold") + requested_similar_room_type_amount)
    )

В приведенном выше фрагменте я хочу, чтобы следующая строка работала таким образом, чтобы при пропущении одной даты другие не возвращались. Что действительно происходит в операторе range / in, так это то, что если он находит одну или несколько совпадающих данных, он возвращает эти данные в набор запросов. Но это не то, что мне нужно. Мне нужно убедиться, что если все даты совпадают, то только вернуть набор запросов, в противном случае он должен быть пустым.

Q (hotel_log__date__range = [check_in_date, check_out_date])

Мы также можем использовать оператор "in", если возможно решение для оператора in. В этом случае фрагмент кода будет:

Q (hotel_log__date__range = date_list)

Для лучшего понимания я добавляю модели также


class BoardRate(models.Model):
   STATUS_CHOICES = [("OP", "open"), ("CL", "close")]
   RATE_CHOICES = [("NOR", "refundable"), ("NRF", "non-refundable")]
   id = models.BigAutoField(primary_key=True)
   hotel_log = models.ForeignKey(
       "hotel_dashboard.HotelLogBook", on_delete=models.CASCADE, blank=True, null=True)
   room_status = models.CharField(
       max_length=25, choices=STATUS_CHOICES, default="OP")
   room_rate = models.DecimalField(default=0, max_digits=10, decimal_places=2)
   board_type = models.ForeignKey(
       UnifiedHotelBoardType, on_delete=models.CASCADE, related_name='hotel_log')
   rate_class = models.CharField(
       max_length=3, blank=True, choices=RATE_CHOICES, default="NRF")


class HotelLogBook(models.Model):
   log_id = models.BigAutoField(primary_key=True)
   hotel = models.ForeignKey(
       UnifiedHotel, on_delete=models.CASCADE, related_name='hotel_log')
   room = models.ForeignKey(
       UnifiedHotelRoomDetailsPerHotelPerRoom, on_delete=models.CASCADE, related_name='room_log')
   date = models.DateField(null=True, blank=True)
   room_to_sell = models.PositiveIntegerField(default=0)
   room_sold = models.PositiveIntegerField(default=0)
   board_rate = models.ManyToManyField(
       BoardRate, related_name="hotel_log_boards", blank=True)

Пример:

Предположим, что в таблице 13, 14, 15, 16, 17 апреля, а в фильтре мы ищем 13-19 апреля. Теперь, если мы используем оператор «in», мы получим данные с 13 по 17 апреля, но я этого не хочу. Если какой-либо из дней с 13 по 19 апреля данные недоступны, тогда мне нужен пустой набор запросов.

Прогноз:

Я полагаю, что это можно сделать, используя "когда "и" тогда "или" дело ", но я здесь потерян. Может ли кто-нибудь наставить меня на это?

1 Ответ

0 голосов
/ 05 апреля 2020

Вы можете посчитать количество связанных дат и отфильтровать, где количество равно числу ожидаемых вами дат

Model.objects.filter(
    model_two__date__range=[start_date, end_date]
).annotate(
    num_days=Count('model_two__date', distinct=True)
).filter(
    num_days=(end_date - start_date).days + 1
)
...