使用prefetch_related在两个表上的两个过滤器

时间:2016-03-22 21:07:43

标签: django django-models django-views django-queryset

让我们假设这是我的模特:

class Pizza(models.Model):
    size = models.IntegerField()
    #other fields

class Order(models.Model):
    date = models.DateField()
    pizza = models.ManyToManyField(Pizza, through='OrderPizza')
    #other fields


class OrderPizza(models.Model):
    update = models.BooleanField()
    order = models.ForeignKey(Order, on_delete=models.CASCADE)
    pizza = models.ForeignKey(Pizza, on_delete=models.CASCADE)

我尝试在最后一个订单中查看大小为32的披萨的ID。如何只使用一个查询集来执行此操作?

#I take the last order:
last_order =  Orders.objects.filter().order_by('-order_number')[:1]

#If we have at least one order
if last_order:
    var_last_order_id = last_order[0].id
    #First filter
    queryset_orders = Orders.objects.filter(id=var_last_order_id).prefetch_related('pizza')

    for food in queryset_orders:
        #Second filter
        pizza32 = food.pizza.filter(size = 32)
        print pizza32.id

3 个答案:

答案 0 :(得分:0)

我可能会误解你的要求,但听起来你可以这么做:

if Order.objects.exists():
    last_order = Order.objects.order_by('-order_number')[:1]
    pizza32 = last_order.pizza.filter(size=32)

queryset_orders上的循环是不必要的,因为last_order已经是最新的订单。

答案 1 :(得分:0)

您可以通过以下方式获取披萨尺寸为32的订单:

orders = Orders.objects.filter(pizza__size=32)

您可以通过以下方式获取最后一个订单:

last_order = Orders.objects.filter(
    pizza__size=32,
).order_by('-order_number')[0]

使用prefetch_related,您可以在同一查询中获取比萨饼:

last_order = Orders.objects.filter(
    pizza__size=32,
).order_by('-order_number').prefetch_related('pizza')[0]

现在,当您执行last_order.pizza.all()时,不会有任何其他SQL查询。如果您知道订单中只有一个披萨,您可以这样做:

for pizza in last_order.pizza.all():
    pizza

或者从订单中获得第一个披萨:

last_order.pizza.all()[0]

答案 2 :(得分:0)

我也不太清楚你想要摆脱的代码部分。 如果您已经检索了最后一个订单,则可以执行以下操作:

pizza32 = Pizza.objects.filter(order=last_order, size=32)

当然会给你一个披萨查询集,所以你不能做pizza32.id

如果您只想要披萨并且未事先检索订单,则可以加入查询。这将创建一个在一个SQL语句中执行的查询:

pizza32 = Pizza.objects.filter(order__in=Order.objects.order_by('-order_number')[:1], size=32)