我有一个视图,它需要来自第三、第四级关系中许多相关对象的数据。
下面是视图:
class OrderViewSet(ModelViewSet):
queryset = Order.objects.select_related().prefetch_related().order_by('-id')
现在,在序列化器中,我必须获取此订单的相关项目的库存,然后对其执行某些计算。
class OrderListSerializer(ModelSerializer):
shortages = SerializerMethodField()
def get_shortages(self, obj):
item = obj.order_line.product.item
stock = (
order_line.product.item.item_instances.filter(stock_quantity__gt=0)
.aggregate(stock=Coalesce(Sum("stock_quantity"), 0, output_field=FloatField()))
.get("stock", 0)
)
required_stock = self.calculate_required_stock()
if stock < required_stock: .....
在上面的代码中,order_line.product.item.item_instances
行表示4个模型,如果我用('order_line__product__item')
和('order_line__product__item__item_instances')
填充查询集的prefetch_related,发送到数据库的查询仍然是以千为单位的。
我怎样才能改善这种情况。
更新新增示例机型
class Order(models.Model):
order_line = models.ForeignKey(
"OrderLine",
on_delete=models.CASCADE,
related_name="orders",
)
type = models.CharField(choices=TYPE_CHOICES, max_length=13, blank=True)
start_date = models.DateField(blank=True, null=True)
....................
class OrderLine(models.Model):
sales_order = models.ForeignKey(
"SalesOrder",
on_delete=models.CASCADE,
related_name="sales_order_lines",
)
product = models.ForeignKey("Product", on_delete=models.PROTECT)
quantities = models.JSONField(null=True, blank=True)
..............................
class Product(models.Model):
design = models.ForeignKey(
Design, on_delete=models.PROTECT, related_name="design_products"
)
item = models.ForeignKey(
Item, on_delete=models.PROTECT, related_name="item_products"
)
...............................
class Item(models.Model):
shrinkage = models.FloatField(default=0.0)
..............................
class ItemInstance(models.Model):
item = models.ForeignKey(
Item, on_delete=models.PROTECT, related_name="item_instances"
)
stock_quantity = models.FloatField(
default=0.0, blank=True, validators=[MinValueValidator(0)]
)
1条答案
按热度按时间u5rb5r591#
prefetch_related
将填充order_line.product.item.item_instances
上的一些缓存。如果您尝试对查询集执行.filter
或任何其他操作,从而使.prefetch_related
调用无效,则此缓存将被丢弃。你可以这样做: