Проблема оптимизации запросов Django Rest FrameworkPython

Программы на Python
Ответить
Anonymous
 Проблема оптимизации запросов Django Rest Framework

Сообщение Anonymous »

Я новичок в django и какое-то время застрял в этой проблеме. У меня есть модель ProductVariant, модель обзора (используется специальный менеджер, который я предоставлю здесь)
и моя класс сериализатора:

Код: Выделить всё

class ApprovedReviewManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status='approved')

class ProductVariant(models.Model):
class SizeChoices(models.TextChoices):
SMALL = 'sm', 'SMALL'
MEDIUM = 'md', 'MEDIUM'
LARGE = 'lg', 'LARGE'
XLARGE = 'xlg', 'XLARGE'
XXLARGE = 'xxlg', 'XXLARGE'

product = models.ForeignKey(Product,
on_delete=models.CASCADE,
related_name='variants')
size = models.CharField(
SizeChoices.choices,
default=SizeChoices.MEDIUM
)
color = models.CharField(max_length=100)
price = models.DecimalField(decimal_places=2, max_digits=8)
image = models.ImageField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return f'{self.product.name} in {self.color} and {self.size}'

@property
def rating_avg(self):
return Review.approved.filter(
product=self,
status='approved'
).aggregate(avg_rating=Avg('rate'))['avg_rating']

@property
def rating_count(self):
return Review.approved.filter(
product=self,
status='approved'
).count()

@property
def ratings(self):
return Review.approved.filter(
product=self,
status='approved'
)

class Review(models.Model):
class RateChoices(models.TextChoices):
FIVE = '5', 'FIVE'
FOUR = '4', 'FOUR'
THREE = '3', 'THREE'
TWO = '2', 'TWO'
ONE = '1', 'ONE'

class ReviewStatus(models.TextChoices):
APPROVED = 'approved', "APPROVED"
PENDING = 'pending', 'PENDING'
REJECTED = 'rejected' 'REJECTED'

user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(
ProductVariant,
on_delete=models.CASCADE,
related_name='ratings'
)
message = models.TextField()
rate = models.SmallIntegerField(choices=RateChoices.choices,
default=RateChoices.FOUR)
status = models.CharField(choices=ReviewStatus.choices)
datetime = models.DateTimeField(default=timezone.now)

def __str__(self):
return f'{self.user.username} rated {self.product.product.name} {self.rate} stars'

class Meta:
ordering = ['-datetime']

objects = models.Manager()
approved = ApprovedReviewManager()
а вот классы сериализатора, которые я использую:

Код: Выделить всё

class RatingSerializer(serializers.ModelSerializer):
class Meta:
model = Review
fields = ['id', 'rate', 'message', 'datetime', 'status']

class ProductVariantSerializer(serializers.ModelSerializer):
rating_avg = serializers.FloatField()

class Meta:
model = ProductVariant
fields = [
'id', 'product', 'size', 'color',
'price', 'image', 'rating_avg'
]

class ProductVariantDetailSerializer(serializers.ModelSerializer):
rating_avg = serializers.FloatField()
rating_count = serializers.IntegerField()
ratings = RatingSerializer(many=True, source='approved_ratings')

class Meta:
model = ProductVariant
fields = [
'id', 'product', 'size', 'color', 'price', 'image',
'created_at', 'updated_at', 'rating_avg', 'rating_count', 'ratings'
]
Моя проблема в том, что, когда я использую ProductVariantSerializer, у меня есть два запроса (я использую django Silk), но когда я меняю сериализатор на ProductVariantDetailSerializer, это почти 120, это вид, который я использую:

Код: Выделить всё

class HomePagePopularProducts(generics.ListAPIView):
serializer_class = serializers.ProductVariantSerializer
permission_classes = [AllowAny]

def get_queryset(self):
return ProductVariant.objects.prefetch_related(
Prefetch(
'ratings',
queryset=Review.approved.all(),
to_attr='approved_ratings'
)
).annotate(
avg_rat=Avg('ratings__rate'),
).order_by('avg_rat')[:10]
поскольку я использую prefetch_related, я думал, что запрос будет оптимизирован, но, похоже, это не так, что я сделал не так?

Подробнее здесь: https://stackoverflow.com/questions/793 ... on-problem
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»