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
. Таким образом, он запросит базу данных один раз.
Но моделирование выглядит не очень эффективным: базы данных обычно должны быть линейными. Это означает, что два элемента одной и той же "категории" хранятся не в разных столбцах, а в разных строках. Это делает запросы, особенно в данном случае, намного удобнее.