我有名为产品,材料和标签的模型。每种产品都有很多材料,每种材料都有很多标签。每个产品都有标签(不是实际关系),标签定义为产品材料的所有不同标签。我想将带有标签属性的Product queryset传递给django rest序列化器,而不会出现N + 1问题。
我使用了子查询,但是它只返回一行和一列。我试图在python级别上操作它,但是它会产生N + 1问题,即使我设法避免了N + 1问题,它也会比使用ORM慢,因为它是python。我尝试添加与产品相关的标签,并在每次更改材料和/或材料的标签时进行更新,并使用prefetch_related查询它,因此它没有N + 1,它的效果很好,但是为我的代码添加了更多的复杂性这么简单。因此,我不想在产品中添加标签关系。
class Product(models.Model):
name = models.CharField(max_length=255)
class Material(models.Model):
name = models.CharField(max_length=255)
product = models.ForeignKey(Product, related_name='materials', on_delete=models.CASCADE)
class Tag(models.Model):
name = models.CharField(max_length=255)
material = models.ForeignKey(Material, related_name='tags', on_delete=models.CASCADE)
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
class ProductSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True)
class Meta:
model = Product
fields = '__all__'
我希望查询集可以传递给ProductSerializer,而不会出现N + 1问题,并且无需使用信号。
答案 0 :(得分:3)
您不需要自己加载相关对象。 Django有工具为您做到这一点。您可以使用.prefetch_related(..)
[Django-doc]。这将使查询通过附加查询来检索相关对象,然后将这些对象链接到相关对象。因此,它基本上在Python / Django端执行JOIN,并且仅对这些JOIN使用恒定数量的查询:
products = Product.objects.prefetch_related('materials__tags')
serializer = ProductSerializer(products, many=True)
因此,在此我们避免使用另一个查询为每个tags
提取Product
。