Как удалить похожие и дублирующиеся запросы в django rest framework?
Когда я вызываю конечную точку продукта, происходят дублирующие и похожие запросы для среднего рейтинга. Я использовал prefetch_related для решения этой проблемы, но кажется, что использованный мной способ не является правильный. Помогите мне, пожалуйста, решить эту проблему.
Вот структура модели
models.py
class Product(models.Model):
name = models.CharField(max_length=255)
vendor = models.ForeignKey(
Vendor,
on_delete=models.CASCADE,
)
class ProductRating(models.Model):
product_id = models.ForeignKey(
Product,
on_delete=models.CASCADE,
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
maxval=5
message='Rating must be less than 5'
rate =models.PositiveIntegerField(validators=[MaxValueValidator(maxval,message)],null=True)
comment = models.TextField(blank=True,null=True)
seller_reply = models.TextField(blank=True,null=True)
reply_at=models.DateTimeField(auto_now=True)
created_at=models.DateTimeField(auto_now=False,auto_now_add=True)
class VendorRating(models.Model):
product_id = models.ForeignKey(
Product,
on_delete=models.CASCADE,
)
vendor_id=models.ForeignKey(
Vendor,
on_delete=models.CASCADE
)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
maxval=5
message='Rating must be less than 5'
communication_rate=models.PositiveIntegerField(validators=[MaxValueValidator(maxval,message)],null=True,blank=True)
product_quality_rate=models.PositiveIntegerField(validators=[MaxValueValidator(maxval,message)],null=True,blank=True)
experience_rate=models.PositiveIntegerField(validators=[MaxValueValidator(maxval,message)],null=True,blank=True)
created_at=models.DateTimeField(auto_now=False,auto_now_add=True)
в файле views.py
def get_queryset(self):
queryset=self.get_serializer().setup_eager_loading(Product.objects.all())
return queryset
в serializers.py
class ProductSerializer(TaggitSerializer, serializers.ModelSerializer):
avg_productrating = serializers.SerializerMethodField("get_rating")
avg_vendorrating=serializers.SerializerMethodField("get_avgvendorrating")
def get_rating(self, obj):
rating=obj.productrating_set.all().aggregate(avg=Avg("rate"))['avg']
average_rate=round(rating,2) if rating else rating
return average_rate
def get_avgvendorrating(self,obj):
try:
average_rate=obj.vendor.vendorrating_set.all().aggregate(
Avg("communication_rate"),Avg('product_quality_rate'),Avg("experience_rate")
)
rates=[rate for rate in average_rate.values() if rate is not None]
if(not rates):
total=0
else:
total=sum(rates)/3
return round(total,2)
except:
return 0
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset=queryset.prefetch_related(Prefetch('vendor',queryset=Vendor.objects.prefetch_related('user','vendorrating_set')))
в urls.py
rom rest_framework import routers
from . import views
router = routers.SimpleRouter()
router.register(r"product", views.ProductViewSet,basename='products')
вывод в debug-tools
SELECT AVG("buysell_productrating"."rate") AS "avg"
FROM "buysell_productrating"
WHERE "buysell_productrating"."product_id_id" = '3' 3 similar queries.
SELECT AVG("buysell_vendorrating"."communication_rate") AS "communication_rate__avg",
AVG("buysell_vendorrating"."product_quality_rate") AS "product_quality_rate__avg",
AVG("buysell_vendorrating"."experience_rate") AS "experience_rate__avg"
FROM "buysell_vendorrating"
WHERE "buysell_vendorrating"."vendor_id_id" = '1' 3 similar queries. Duplicated 2 times.