rateing system
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user