仅当另一个对象在查询集中时才从查询集中过滤掉对象
Filter out objects from queryset only if another object is in queryset
考虑一个非常简单的模型:
class Thing(models.Model):
attribute = models.IntegerField(choices=[1,2,3])
我想要所有东西,除了那些属性为 2 的东西。
但如果结果集中没有属性为 2 的事物,我确实希望这些属性为 2。
如何通过单个查询获得此结果?
[编辑]
实际上,我只需要第一个属性不同于 2 的事物,或者第一个属性为 2 的事物(如果这是唯一可用的事物)。
我已经能够通过
函数实现这一点
def get_thing():
things_per_attribute = [
Thing.objects.filter(attribute=value)
for value in [1, 3, 2]
]
for thing in things_per_attribute:
if thing.count() > 0:
return thing[0]
return None
我仍然有兴趣看看是否有人可以提出 1-query-solution。
一个查询:
from django.db.models import BooleanField, Case, When
Thing.objects.annotate(
attribute_is_two=Case(
When(attribute=2, then=True),
default=False,
output_field=BooleanField()
),
).order_by('-attribute_is_two').first()
两个查询:
def get_thing():
thing = Things.objects.exclude(attribute=2).first()
if thing:
return thing
return Thing.objects.first()
考虑一个非常简单的模型:
class Thing(models.Model):
attribute = models.IntegerField(choices=[1,2,3])
我想要所有东西,除了那些属性为 2 的东西。
但如果结果集中没有属性为 2 的事物,我确实希望这些属性为 2。
如何通过单个查询获得此结果?
[编辑]
实际上,我只需要第一个属性不同于 2 的事物,或者第一个属性为 2 的事物(如果这是唯一可用的事物)。
我已经能够通过
函数实现这一点def get_thing():
things_per_attribute = [
Thing.objects.filter(attribute=value)
for value in [1, 3, 2]
]
for thing in things_per_attribute:
if thing.count() > 0:
return thing[0]
return None
我仍然有兴趣看看是否有人可以提出 1-query-solution。
一个查询:
from django.db.models import BooleanField, Case, When
Thing.objects.annotate(
attribute_is_two=Case(
When(attribute=2, then=True),
default=False,
output_field=BooleanField()
),
).order_by('-attribute_is_two').first()
两个查询:
def get_thing():
thing = Things.objects.exclude(attribute=2).first()
if thing:
return thing
return Thing.objects.first()