You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django数据迁移后平均评分计算失效、choices参数未生效修复

Django迁移后商品平均评分计算失效修复方案

问题根因

该问题并非迁移未识别choices参数,实际是代码定义错误导致,核心问题有3个:

  • Review模型存在重复的rating字段定义:类中先声明了整数类型的rating = models.IntegerField(default=3),后续又重新声明了字符串类型的rating = models.CharField(max_length=7,choices= RATINGS),Python类属性以后定义的为准,执行AlterField迁移后,数据库中rating字段从整数类型被修改为字符串类型,和计算逻辑的数值预期冲突。
  • RATINGS配置不符合Django choices规范:
    • choices标准格式为( (数据库实际存储值, 页面展示值), ... ),当前代码把带尾部空格的字符串作为存储值、整数作为展示值,顺序完全写反。
    • 存储值使用了带多余尾部空格的字符串(如'1 '而非'1'),引入不必要的格式异常。
  • 平均评分计算逻辑无类型兼容处理:迁移后rating字段存储的是字符串类型,直接执行reviews_total += review.rating会触发类型错误,无法完成数值累加,直接导致计算失效。

相关错误迁移片段截图:
迁移片段截图

修复步骤

  1. 修正Review模型代码,删除重复字段定义,调整RATINGS配置和字段类型(评分用整数存储更合理),修正后代码如下:
class Review(models.Model):
    RATINGS = (
        (1, '1星'),
        (2, '2星'),
        (3, '3星'),
        (4, '4星'),
        (5, '5星'),
    )
    product = models.ForeignKey(Product, related_name='reviews', on_delete=models.CASCADE)
    rating = models.IntegerField(choices=RATINGS, default=3)
    content = models.TextField()
    created_by = models.ForeignKey(User, related_name='reviews', on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '%s - %s' % (self.product.name, self.created_by)
  1. 存量数据修正:如果执行错误迁移后已经存入了字符串格式的评分数据,先进入Django shell做数据转换,避免后续迁移报错:
    执行shell命令:
    python manage.py shell
    在shell中执行数据转换逻辑:
from products.models import Review
for review in Review.objects.all():
    try:
        # 去除字符串首尾空格后转为整数
        review.rating = int(str(review.rating).strip())
        review.save()
    except (TypeError, ValueError):
        # 转换失败的异常数据用默认3分填充
        review.rating = 3
        review.save()
  1. 生成并执行新的迁移:
    执行命令生成迁移文件,此时Django会正确识别choices配置,生成将rating字段改回整数类型的迁移:
    python manage.py makemigrations
    确认迁移文件内容无误后执行迁移:
    python manage.py migrate
  2. (可选优化)为评分计算逻辑增加异常兼容,避免后续因脏数据导致计算失效,修改Product类的get_rating方法:
def get_rating(self):
    reviews = self.reviews.all()
    review_count = reviews.count()
    if review_count == 0:
        return 0
    reviews_total = 0
    for review in reviews:
        try:
            reviews_total += int(review.rating)
        except (TypeError, ValueError):
            # 遇到异常评分直接跳过,也可根据业务需求按默认值计算
            continue
    # 保留2位小数返回,和Product自身rating字段精度对齐
    return round(reviews_total / review_count, 2)

内容的提问来源于stack exchange,提问作者tobias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:21:23