Как обновить поле модели на основе другой модели в Django?
У меня есть две модели в Django.
Один для продуктов, а другой - для рейтингов.
Модель продукта:
class Product(models.Model):
...
product_name = models.CharField(max_length=264, blank=False, verbose_name='Product Name')
product_slug = models.SlugField(blank=True)
avg_rating = models.IntegerField(blank=True, null=True, verbose_name='Average Rating', help_text='Do not Edit!')
total_rating_count = models.IntegerField(blank=True, null=True, verbose_name='Total Rating', help_text='Do not Edit!')
def save(self, *args, **kwargs):
...
super(Product, self).save(*args, **kwargs)
def __str__(self):
return self.product_name
Рейтинговая модель:
class Rating(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='product_ratings')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_rating')
product_rating = models.IntegerField(verbose_name='Rating', blank=False)
product_comment = models.TextField(verbose_name='Comment', blank=False)
Я хочу сделать так: когда пользователь оценивает продукт, я хочу обновить avg_rating
и total_rating_count
в модели Product.
Как я могу это сделать? Спасибо.
Повторяя слова Виллема, я бы удалил эти поля и вычислил их следующим образом:
from django.db.models import Avg
class Product(models.Model):
...
product_name = models.CharField(max_length=264, blank=False, verbose_name='Product Name')
product_slug = models.SlugField(blank=True)
@property
def avg_rating(self):
return self.product_ratings.all().aggregate(Avg('product_rating'))['product_rating__avg']
@property
def total_rating_count(self):
return self.product_ratings.all().count()
Затем вы можете получить доступ к этой информации, как к любому другому атрибуту:
product = Product.objects.first()
product.avg_rating
Я бы рассмотрел возможность использования cached_property по соображениям производительности.