I have models.py
class Category(MPTTModel):
# few fields
class Brand(models.Model):
# few fields
class Attribute(models.Model):
# few fields
class AttributeValue(models.Model):
attributes = models.ForeignKey(Attribute, # other conditions)
# few fields
class Product(models.Model):
category = models.ForeignKey(Category, # other conditions)
brand = models.ForeignKey(Brand, # other conditions)
attributes = models.ManyToManyField(Attribute, # other conditions)
# few other fields
class ProductImages(models.Model):
product = models.ForeignKey(Product, # other conditions)
In views.py
, I have
class ProductAPIView(generics.GenericAPIView):
serializer_class = ProductSerializer
queryset = Product.objects.all()
serializers.py
class ProductSerializer(serializers.ModelSerializer):
brand = serializers.SlugRelatedField(queryset = Brand.objects.all())
category = serializers.SlugRelatedField(queryset = Category.objects.all())
attributes = AttributeSerializer(many = True, read_only = True)
product_images = ProductImageSerializer(many = True, read_only = True)
I'm getting my json response like this
{
"brand": ...,
"category": ...,
"attributes": [
{ "attribute_values": [...] },
{ "attribute_values": [...] }
],
"product_images": [{...}, {...}]
}
I came across select_related
and prefetch_related
which will optimise the db queries on foreign key fields and many-to-many fields.
I changed the queryset to queryset = Product.objects.select_related('category', 'brand').all()
How can i change the queryset in ProductAPIView to include the attributes
, product_images
and attribute_values
fields also and improve the performance here ?
you can chain select_realted
& prefetch_related
class ProductAPIView(generics.GenericAPIView):
serializer_class = ProductSerializer
queryset = Product.objects.select_related('category', 'brand').prefetch_related("attributes")
or override get_queryset
function
class ProductAPIView(generics.GenericAPIView):
serializer_class = ProductSerializer
def get_queryset(self):
qs = super().get_queryset()
return qs.select_related('category', 'brand').prefetch_related("attributes")
You can use the Prefetch class to specify the queryset that is used in prefetch_related() and this way combine it with select_related():