Django queryset - исключение значений True

Я пытаюсь построить набор запросов, в который добавляются только истинные значения.

Модели

Models
reference = models.CharField(validators=[MinLengthValidator(15)], max_length=25, primary_key=True)
h0730 = models.BooleanField(default=False)
h0800 = models.BooleanField(default=False)
h0830 = models.BooleanField(default=False)
h0900 = models.BooleanField(default=False)
h0930 = models.BooleanField(default=False)
h1000 = models.BooleanField(default=False)
h1030 = models.BooleanField(default=False)
h1100 = models.BooleanField(default=False)
h1130 = models.BooleanField(default=False)
h1200 = models.BooleanField(default=False)
h1230 = models.BooleanField(default=False)
h1300 = models.BooleanField(default=False)
h1330 = models.BooleanField(default=False)
h1400 = models.BooleanField(default=False)
h1430 = models.BooleanField(default=False)
h1500 = models.BooleanField(default=False)
h1530 = models.BooleanField(default=False)
delivery_date = models.CharField(max_length=8)
is_cancelled = models.BooleanField(default=False)

Виды

taken_slots = Order.objects.filter(delivery_date__exact=delivery_date).filter(reference__icontains=code).filter(is_cancelled=False)

slots_remaining = ['h0730', 'h0800', 'h0830', 'h0900', 'h0930', 'h1000', 'h1030', 'h1100', 'h1130', 'h1200', 'h1230', 'h1300', 'h1330', 'h1400', 'h1430', 'h1500', 'h1530']

for slot in taken_slots:
    if slot.h0730 and 'h0730' in slots_remaining:
        slots_remaining.remove('h0730')
    if slot.h0800 and 'h0800' in slots_remaining:
        slots_remaining.remove('h0800')
        ...
        ...

Приведенный выше цикл for работает, как и ожидалось, но я пытаюсь оптимизировать процесс. Например, если есть 100 ссылок за день, "taken_slots" будет итерироваться 100 раз.

После завершения цикла for ожидается, что в списке "slots_remaining" останутся только значения False, например

ref1 = h0730 and h0930 is True and every other slot False
ref2 = h0900 is True and every other slot False
ref3 = h1030 is True and every other slot False
ref4 = h1230 is True and every other slot False
ref5 = h1300 and h1330 is True and every other slot False
ref6 = h1500 is True and every other slot False

If h0730, h0900, h0930, h1030, h1230, h1300, h1330, h1500 from 6 references are True.
slots_remaining must remain with ['h0800', 'h0830', 'h1000', 'h1100', 'h1130', 'h1200', 'h1400', 'h1430', 'h1530']

Есть ли способ построить список slots_remaining непосредственно из запроса taken_slots или, по крайней мере, избежать цикла for. Я видел примеры с использованием distinct, annotate и union, но, вероятно, делаю это неправильно, поскольку мне не удалось заставить их работать.

Я не понял, что вы сказали в последнем абзаце. но вы можете использовать функцию исключения следующим образом:

exclude_param = {item: True for item in slots_remaining}
taken_slots = taken_slots.exclude(**exclude_param)

Надеюсь, у вас получится. Если нет, объясните подробнее последний абзац.

Не понимаю, зачем перечислять 100 раз, вы можете работать с множеством и, таким образом, работать с:

slots_remaining = {
    'h0730',
    'h0800',
    'h0830',
    'h0900',
    'h0930',
    'h1000',
    'h1030',
    'h1100',
    'h1130',
    'h1200',
    'h1230',
    'h1300',
    'h1330',
    'h1400',
    'h1430',
    'h1500',
    'h1530',
}


for slot in taken_slots:
    slots_remaining -= {name for name in slot_remaining if getattr(slot, name)}

при этом будет перечисляться раз над taken_slots, и для каждого слота каждый раз проверять только оставшиеся один раз. В конце цикла оставшиеся один раз все еще находятся в slots_remaining. Таким образом, он запросит базу данных один раз.

Но моделирование выглядит не очень эффективным: базы данных обычно должны быть линейными. Это означает, что два элемента одной и той же "категории" хранятся не в разных столбцах, а в разных строках. Это делает запросы, особенно в данном случае, намного удобнее.

Вернуться на верх