我有以下型号:
class Order_type(models.Model):
description = models.CharField()
class Order(models.Model):
type= models.ForeignKey(Order_type)
order_date = models.DateField(default=datetime.date.today)
status = models.CharField()
processed_time= models.TimeField()
我想要一个包含符合此条件的订单的订单类型列表:(order_date
< =今天且processed_time
为空,status
不为空白
我试过了:
qs = Order_type.objects.filter(order__order_date__lte=datetime.date.today(),\
order__processed_time__isnull=True).exclude(order__status='')
这适用于原始订单列表:
orders_qs = Order.objects.filter(order_date__lte=datetime.date.today(), processed_time__isnull=True)
orders_qs = orders_qs.exclude(status='')
但是qs
不是正确的查询集。我认为它实际上返回了一个更窄的过滤器(因为没有记录)但我不确定是什么。根据这个(django reference),因为我引用了一个相关的模型,我认为排除适用于原始查询集(不是过滤器中的那个),但我没有得到确切的结果。
好吧,我只是想到了这个,我觉得有用,但感觉很草率(有更好的方法吗?):
qs = Order_type.objects.filter(order__id__in=[o.id for o in orders_qs])
答案 0 :(得分:6)
正在发生的事情是,exclude()查询正在为您搞砸。基本上,它排除了任何至少有一个没有状态的订单的Order_type,这几乎肯定不是你想要发生的。
在您的情况下,最简单的解决方案是在您的filter()参数中使用order__status__gt=''
。但是,您还需要将distinct()
附加到查询的末尾,否则如果具有多个与查询匹配的Order,则会获得具有相同Order_type的多个实例的QuerySet。这应该有效:
qs = Order_type.objects.filter(
order__order_date__lte=datetime.date.today(),
order__processed_time__isnull=True,
order__status__gt='').distinct()
在旁注中,在问题结尾处给出的qs查询中,您不必说order__id__in=[o.id for o in orders_qs]
,您只需使用order__in=orders_qs
(您还需要{ {1}})。所以这也有效:
distinct()
附录(编辑):
以下是Django为上述查询集发出的实际SQL:
qs = Order_type.objects.filter(order__in=Order.objects.filter(
order_date__lte=datetime.date.today(),
processed_time__isnull=True).exclude(status='')).distinct()
EXPLAIN显示,第二个查询的价格要贵得多(成本为28.99,而数据集非常小,为28.64)。