我想计算评分的平均值(在评论模型中)并将其发送到我的 API。
模型.py
from django.db import models
from adminuser.models import Categories
from accounts.models import UserAccount as User
from django.core.validators import MaxValueValidator, MinValueValidator
# Create your models here.
class Gigs(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey(Categories , on_delete=models.CASCADE)
price = models.DecimalField(max_digits=6, decimal_places=2)
details = models.TextField()
seller = models.ForeignKey(User,default=None, on_delete=models.CASCADE)
class Reviews(models.Model):
rating = models.SmallIntegerField( default=0,validators=[MaxValueValidator(5),MinValueValidator(1)])
comment = models.CharField(max_length=500)
item = models.ForeignKey(Gigs , on_delete=models.CASCADE)
buyer = models.ForeignKey(User ,default=None, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
Views.py
from django.shortcuts import render
from .models import Gigs,Reviews
from .serializers import GigsSerializer,ReviewsSerializer
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import ListModelMixin, CreateModelMixin , RetrieveModelMixin , DestroyModelMixin, UpdateModelMixin
from rest_framework.permissions import AllowAny
# Create your views here.
#List and create (pk not required)
class GigsListAPI(GenericAPIView, ListModelMixin ):
def get_queryset(self):
username = self.kwargs['user']
return Gigs.objects.filter(seller=username)
serializer_class = GigsSerializer
permission_classes = (AllowAny,)
def get(self, request , *args, **kwargs):
return self.list(request, *args, **kwargs)
class GigsListCategorywise(GenericAPIView, ListModelMixin ):
def get_queryset(self):
SearchedCategory = self.kwargs['category']
return Gigs.objects.filter(category=SearchedCategory)
serializer_class = GigsSerializer
permission_classes = (AllowAny,)
def get(self, request , *args, **kwargs):
return self.list(request, *args, **kwargs)
class GigsListAll(GenericAPIView, ListModelMixin ):
queryset = Gigs.objects.all()
serializer_class = GigsSerializer
permission_classes = (AllowAny,)
def get(self, request , *args, **kwargs):
return self.list(request, *args, **kwargs)
class GigsCreateAPI(GenericAPIView, CreateModelMixin):
queryset = Gigs.objects.all()
serializer_class = GigsSerializer
permission_classes = (AllowAny,)
def post(self, request , *args, **kwargs):
return self.create(request, *args, **kwargs)
# Retrieve, update and delete (pk required)
class RUDGigsAPI(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Gigs.objects.all()
serializer_class = GigsSerializer
permission_classes = (AllowAny,)
def get(self, request , *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request , *args, **kwargs):
return self.update(request, *args, **kwargs)
def put(self, request , *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
def delete(self, request , *args, **kwargs):
pk = kwargs.get('pk')
p = Gigs.objects.get(id=pk)
if p.images:
p.images.delete()
return self.destroy(request, *args, **kwargs)
# VIEWS FOR REVIEWS MODEL
class ReviewsListAPI(GenericAPIView, ListModelMixin ):
def get_queryset(self):
item = self.kwargs['item']
return Reviews.objects.filter(item=item)
serializer_class = ReviewsSerializer
permission_classes = (AllowAny,)
def get(self, request , *args, **kwargs):
return self.list(request, *args, **kwargs)
class ReviewsCreateAPI(GenericAPIView, CreateModelMixin):
queryset = Reviews.objects.all()
serializer_class = ReviewsSerializer
permission_classes = (AllowAny,)
def post(self, request , *args, **kwargs):
return self.create(request, *args, **kwargs)
序列化器.py
from rest_framework import serializers
from .models import Gigs, Reviews
class GigsSerializer (serializers.ModelSerializer):
class Meta:
model = Gigs
fields = ['id','title','category','price','details','seller','images']
class ReviewsSerializer (serializers.ModelSerializer):
class Meta:
model = Reviews
fields = ['id','rating','comment','item','buyer','created_at']
我想计算评论表中某些演出或项目的平均评分,然后将其发送到 API。但我很困惑在哪里计算它(models.py 或 views.py)以及如何将它发送到我的 API。
最佳答案
好吧,我要详细解释一下,平均评分可以被认为是 Gigs 中的一个虚拟字段,所以把它放在那里是有意义的,所以让我们试试看:
class Gigs(models.Model):
...
@property
def average_rating(self):
return self.reviews.aggregate(Avg('rating'))['rating_avg']
所以当您要检索单个 Gig 时,这很好,但问题是如果您需要列表 api 中的平均值,这将产生很多额外的查询(每个 Gig 1 个)。在这种情况下,最好在 View 中批量执行,因此:
class GigsListAll(ListModelMixin, GenericAPIView): # you should put the mixin before the main class :D
serializer_class = GigsSerializer
permission_classes = (AllowAny,)
def get_queryset(self):
return Gigs.objects.all().annotate(_average_rating=Avg('reviews__rating') # pay attention, it was annotated as _average_rating
现在我们要更改模型中的虚拟场,并检查我们是否预先计算了它,所以:
class Gigs(models.Model):
...
@property
def average_rating(self):
if hasattr(self, '_average_rating'):
return self._average_rating
return self.reviews.aggregate(Avg('rating'))
最后在你的序列化器中使用它:
class GigsSerializer (serializers.ModelSerializer):
average_rating = serializers.SerializerMethodField()
def get_average_rating(self, obj):
return obj.average_rating
class Meta:
model = Gigs
fields = ['id','title','category','price','details','seller','images','average_rating']
附注为外键设置相关名称是最佳实践,因此请像这样更改您的 reviews
模型:
class Reviews(models.Model):
...
item = models.ForeignKey(Gigs , on_delete=models.CASCADE, related_name='reviews')
关于django - 如何计算 Django 模型中某些字段的平均值并将其发送到 rest API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68953258/