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"列表只剩下值为假的数据,比如说:
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 the 6 references are True.
slots_remaining must remain with ['h0800', 'h0830', 'h1000', 'h1100', 'h1130', 'h1200', 'h1400', 'h1430', 'h1530']
有没有办法直接从taken_slots查询构建slots_remaining列表,或者至少避免使用for循环。我见过distinct、annotate和union的例子,但可能是我用错了,没能让它正常工作。
编辑:为了提供更多背景,一个引用的查询集示例可能是这样的:
<QuerySet [{'h0730': True, 'h0800': False, 'h0830': False, 'h0900': False, 'h0930': False, 'h1000': False, 'h1030': False, 'h1100': False, 'h1130': False, 'h1200': False, 'h1230': False, 'h1300': False, 'h1330': False, 'h1400': True, 'h1430': True, 'h1500': True, 'h1530': True}]>
我想要实现的基本上是将多个引用的所有值合并在一起。例如,下面的6个引用应该是一个查询集的一部分。
ref_start = ['h0730', 'h0800', 'h0830', 'h0900', 'h0930', 'h1000', 'h1030', 'h1100', 'h1130', 'h1200', 'h1230', 'h1300', 'h1330', 'h1400', 'h1430', 'h1500', 'h1530']
ref1 = ['True', 'h0800', 'h0830', 'True', 'h0930', 'h1000', 'h1030', 'h1100', 'h1130', 'h1200', 'h1230', 'h1300', 'h1330', 'h1400', 'h1430', 'h1500', 'h1530']
ref2 = ['h0730', 'h0800', 'h0830', 'h0900', 'True', 'h1000', 'h1030', 'h1100', 'h1130', 'h1200', 'h1230', 'h1300', 'h1330', 'h1400', 'h1430', 'h1500', 'h1530']
ref3 = ['h0730', 'h0800', 'h0830', 'h0900', 'h0930', 'h1000', 'True', 'h1100', 'h1130', 'h1200', 'h1230', 'h1300', 'h1330', 'h1400', 'h1430', 'h1500', 'h1530']
ref4 = ['h0730', 'h0800', 'h0830', 'h0900', 'h0930', 'h1000', 'h1030', 'h1100', 'h1130', 'h1200', 'True', 'h1300', 'h1330', 'h1400', 'h1430', 'h1500', 'h1530']
ref5 = ['h0730', 'h0800', 'h0830', 'h0900', 'h0930', 'h1000', 'h1030', 'h1100', 'h1130', 'h1200', 'h1230', 'True', 'True', 'h1400', 'h1430', 'h1500', 'h1530']
ref6 = ['h0730', 'h0800', 'h0830', 'h0900', 'h0930', 'h1000', 'h1030', 'h1100', 'h1130', 'h1200', 'h1230', 'h1300', 'h1330', 'h1400', 'h1430', 'True', 'h1530']
ref_merged = ['True', 'h0800', 'h0830', 'True', 'True', 'h1000', 'True', 'h1100', 'h1130', 'h1200', 'True', 'True', 'h1330', 'h1400', 'h1430', 'True', 'h1530']
ref_merged_without_True = ['h0800', 'h0830', 'h1000', 'h1100', 'h1130', 'h1200', 'h1330', 'h1400', 'h1430', 'h1530']
是否可以直接从查询中获取ref_merged_without_True,还是必须使用循环?
2 个回答
0
我没太明白你在最后一段说的意思。不过你可以这样使用排除函数:
exclude_param = {item: True for item in slots_remaining}
taken_slots = taken_slots.exclude(**exclude_param)
希望这个对你有用。如果不行的话,请再详细解释一下你最后一段的内容。
0
我不明白你为什么要循环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
中。因此,它只会查询数据库一次。
不过,这样的设计看起来不是很有效:数据库通常应该 线性设计。这意味着如果两个项目属于同一“类别”,就不要把它们存储在不同的列中,而是存储在不同的行中。这样查询起来会方便很多,尤其是在这种情况下。