python - 如何重写 Django 模型的 save() 方法以使其正确更新?

标签 python django django-models

我正在为我的学校构建一个评价我的教授类型的应用程序,并进行一些练习。

目前我的models.py看起来像这样:

from __future__ import unicode_literals

from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
from django.contrib.auth.models import User
from django.utils import timezone

UNIVERSITIES = (
    .....
)

DEPARTMENTS = (
    .....
)

class Professor(models.Model):
    name = models.CharField(max_length=255)
    name_code = models.CharField(max_length=3, blank=True)
    university = models.CharField(max_length=3, choices=UNIVERSITIES)
    department = models.CharField(max_length=50, choices=DEPARTMENTS)
    total_rating_points = models.IntegerField(default = 0)
    number_of_reviews = models.IntegerField(default = 0)
    rating = models.FloatField(
        validators = [MinValueValidator(0.0), MaxValueValidator(5.0)],
        default = 0.0
    )

    def __str__(self):
        return self.name

SCORE_CHOICES = (
    .....
)

class Review(models.Model):
    author = models.ForeignKey(User, related_name='user_reviews')
    professor = models.ForeignKey(Professor, related_name='professor_reviews')
    created = models.DateTimeField(default=timezone.now)
    updated = models.DateTimeField(default = timezone.now)
    rating = models.IntegerField(default=1, choices=SCORE_CHOICES)
    text = models.TextField(blank=True)

    class Meta:
        unique_together = [('author', 'professor')]

    def __str__(self):
        return 'Professor: ' +self.professor.name +', Score: ' +str(self.rating)

    def save(self, *args, **kwargs):
        """
        Re-writing the save method to update the associated professor's
        rating as soon as a new Review object is created.
        Also accounts for review updates by the user.
        """
        if self.pk is None:
            # This means that this is a new object
            if self.professor:
                p = self.professor
                # Adjusting the total_rating_points and number of reviews
                p.total_rating_points += self.rating
                p.number_of_reviews += 1
                # Adjusting the rating
                p.rating = float(p.total_rating_points) / float(p.number_of_reviews)
                p.save()
        else:
            # This object already exists, so this is an update
            self.updated = timezone.now()
            **WHAT DO I DO NOW?**


        super(Review, self).save(*args, **kwargs)

你看,如果用户更新了他/她的评分,教授的评分也必须相应调整。由于这是应用程序的核心,我想在 save() 方法中完成它。如果这是一篇非常新的评论,效果会很好。但是,如何更新分数?

我的意思是我知道我必须做什么:

  • 从教授的total_ rating_point中减去之前的分数。

  • 将新评分添加到total_ rating_point

  • 通过除以 number_of_review 来计算评分。

但是,在更新期间如何在 save() 方法中检索之前的分数?还有更好、更有效的方法来完成我想做的事情吗?谢谢!

最佳答案

有几个问题需要记住:如果用户删除他们的帐户、评论等怎么办?按照所示方式保持运行总计将会出现问题。

相反,我建议采用如下所示的结构;当Review更新时,保存它,然后调用Professor的save方法。 Professor 运行的新保存方法会计算现有评论的总和和计数,每次都会重新计算,因为它仍然只访问数据库进行几个查询。

from django.db.models import Sum

class Professor(models.Model):
    ...
    def save(self,*args,**kwargs):
        if self.pk: # prevent hitting the database unless professor already exists
            professor_reviews = Review.objects.filter(professor=self)
            # Adjusting the total_rating_points and number of reviews
            self.total_rating_points = professor_reviews.aggregate(Sum('rating'))
            self.number_of_reviews = professor_reviews.count()
            # Adjusting the rating
            self.rating = float(self.total_rating_points) / float(self.number_of_reviews)
        super(Professor,self).save(*args,**kwargs)

class Review(models.Model):
    ....         
    def save(self, *args, **kwargs):
        if self.pk: #already exists
            self.updated = timezone.now()
        super(Review, self).save(*args, **kwargs) 
        self.professor.save() # call after super writes the Review to the DB

关于python - 如何重写 Django 模型的 save() 方法以使其正确更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35249078/

相关文章:

python - 在 Python 中生成包含 4 列的 1 GB 文件

python - 如何将自定义 javascript 添加到 django-xadmin?

python - django.core.exceptions.ImproperlyConfigured : Requested setting LOGGING_CONFIG, 但未配置设置

python - Django 将 MySQL 查询转换为 Django 查询

Django:form.is_valid 检查后,cleaned_data 缺少图像字段

python - 从员工字典中打印员工对象信息

ios - iOS 的 JSON 反序列化

database - 在 Django 中,如何在我的 models.py 中包含一些默认记录?

django - Django表单:如何在关联的模型中简单地包含所有属性

python - 如何将 python 变量编码为 URL 和网络服务器响应?