rateing system

This commit is contained in:
Parsa Nazer
2026-05-12 08:53:12 +03:30
parent 9041366720
commit e678829a86
7 changed files with 240 additions and 6 deletions
+59 -3
View File
@@ -158,6 +158,7 @@ class DynamicProductSerializer(serializers.ModelSerializer):
main_image = serializers.SerializerMethodField()
customer_pickup_title = serializers.SerializerMethodField()
customer_pickup_description = serializers.SerializerMethodField()
average_rating = serializers.SerializerMethodField()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -174,9 +175,9 @@ class DynamicProductSerializer(serializers.ModelSerializer):
model = ProductModel
fields = "__all__"
view_type = {
'list': ['id', 'name', 'rating', 'slug', 'category', 'colors', 'image', 'best_deal_price_before_discount', 'best_deal_price_after_discount', 'best_deal_discount', 'main_image'],
'slider': ['id', 'name', 'rating', 'slug', 'category', 'variants', 'colors', 'image', 'best_deal_price_before_discount', 'best_deal_price_after_discount', 'best_deal_discount', ],
'instance': ['id', 'name', 'description', 'rating', 'slug', 'meta_description', 'meta_keywords', 'meta_rating', 'category', 'related_products', 'in_pack_items', 'variants', 'colors', 'added_to_favorites', 'image', 'customer_pickup_title', 'customer_pickup_description'],
'list': ['id', 'name', 'rating', 'slug', 'category', 'colors', 'image', 'best_deal_price_before_discount', 'best_deal_price_after_discount', 'best_deal_discount', 'main_image', 'average_rating'],
'slider': ['id', 'name', 'rating', 'slug', 'category', 'variants', 'colors', 'image', 'best_deal_price_before_discount', 'best_deal_price_after_discount', 'best_deal_discount', 'average_rating'],
'instance': ['id', 'name', 'description', 'rating', 'slug', 'meta_description', 'meta_keywords', 'meta_rating', 'category', 'related_products', 'in_pack_items', 'variants', 'colors', 'added_to_favorites', 'image', 'customer_pickup_title', 'customer_pickup_description', 'average_rating'],
'chat': ['id', 'name', 'description', 'variants', 'image']
}
@@ -241,6 +242,39 @@ class DynamicProductSerializer(serializers.ModelSerializer):
# Use exists() with filter instead of fetching all products
return UserFavorites.objects.filter(user=request.user, products=obj).exists()
def get_average_rating(self, obj):
"""Get cached average rating for product - optimized with prefetch"""
from django.core.cache import cache
from django.db.models import Avg
cache_key = f'product_avg_rating_{obj.id}'
avg_rating = cache.get(cache_key)
if avg_rating is None:
# Try to use prefetched ratings if available (no query needed)
try:
prefetched_ratings = obj._prefetched_objects_cache.get('ratings')
if prefetched_ratings is not None:
# Use prefetched data - no database query
ratings_list = [r.rating for r in prefetched_ratings]
if ratings_list:
avg_rating = round(sum(ratings_list) / len(ratings_list), 2)
else:
avg_rating = 0
else:
# Fall back to aggregation query if not prefetched
avg_rating = obj.ratings.aggregate(Avg('rating'))['rating__avg'] or 0
avg_rating = round(avg_rating, 2)
except (AttributeError, KeyError):
# Fall back to aggregation query
avg_rating = obj.ratings.aggregate(Avg('rating'))['rating__avg'] or 0
avg_rating = round(avg_rating, 2)
# Cache for 1 hour
cache.set(cache_key, avg_rating, 3600)
return avg_rating
def get_variants(self, obj):
view_type = self.context.get('view_type')
if view_type == 'slider':
@@ -292,3 +326,25 @@ class BotProductSerializer(serializers.ModelSerializer):
'pk',
'name'
]
class ProductRatingSerializer(serializers.ModelSerializer):
class Meta:
model = ProductRating
fields = ['rating']
def validate_rating(self, value):
if value not in [1, 2, 3, 4, 5]:
raise serializers.ValidationError("امتیاز باید بین 1 تا 5 باشد")
return value
def create(self, validated_data):
product_id = self.context.get('product_id')
user = self.context.get('request').user
rating = ProductRating.objects.create(
product_id=product_id,
user=user,
rating=validated_data['rating']
)
return rating