Отношения модели Django делают средние оценки равными среднему значению поля номера оценок

#django #model #relationship

#django #Модель #отношение

Вопрос:

Итак, у меня есть две модели Django ‘Movie’ и ‘Rating’, я хочу, чтобы поле фильма avg_rating было средним значением оценок, принадлежащих этому полю с номером фильма. Я также хочу, чтобы avg_rating в поле movie обновлялся каждый раз, когда добавляется обзор. Я новичок в Django, поэтому я действительно не знаю, с чего начать. Ниже приведен файл моих моделей. любая помощь была бы оценена

 from django.db import models
from django.db.models import IntegerField, Model
from django.core.validators import MaxValueValidator, MinValueValidator


class Movie(models.Model):
    title = models.CharField(max_length=200)
    date = models.DateField()
    image = models.CharField(max_length=200)
    details = models.CharField(max_length=500)
    genre = models.CharField(max_length=50)
    duration = models.CharField(max_length=20)
    classification = models.CharField(max_length=50)
    avg_rating = models.PositiveSmallIntegerField(
        default=1,
        validators=[
            MaxValueValidator(5),
            MinValueValidator(0)
        ]
    )
    

class Rating(models.Model):

    number = models.IntegerField(
        default=1,
        validators=[
            MaxValueValidator(5),
            MinValueValidator(0)
        ]
    )
    comment = models.CharField(max_length=200, default='')
    movie = models.ForeignKey(Movie, default=1, on_delete=models.CASCADE)
  

Ответ №1:

Один из простых способов — определить в вашем Movie классе метод, возвращающий среднюю оценку вашего Movie объекта. Итак, вам просто нужно добавить следующий код в вашу модель:

 from django.db import models
from django.db.models.functions import Coalesce
from django.db.models import IntegerField, Model
from django.core.validators import MaxValueValidator, MinValueValidator


class Movie(models.Model):
    title = models.CharField(max_length=200)
    date = models.DateField()
    image = models.CharField(max_length=200)
    details = models.CharField(max_length=500)
    genre = models.CharField(max_length=50)
    duration = models.CharField(max_length=20)
    classification = models.CharField(max_length=50)
    
    def rating_avg(self):
        return Rating.objects.filter(movie=self).aggregate(
                avg=Coalesce(models.Avg('number'), 0),
            )['avg']
  

Обратите внимание, что среднее значение рейтинга поля удалено из Movie полей. Теперь у вас есть метод, который вы можете вызывать для каждого Movie объекта, и этот метод вернет вам среднюю оценку для этого объекта в определенное время.

Пример:

 movie_object = Movie.objects.first()
if movie_object:
    print(movie_object.rating_avg()) # will print average rating of that particular object
  

И если вы используете модель Serializer или a ModelForm for Movie , вы также можете добавить имя этого метода к полям этой модели Serializer или ModelForm для вычисления средней оценки для каждого объекта всякий раз, когда вы вызываете представление для этого объекта (т. Е. fields = ['title', ..., 'rating_avg'] ).