【问题标题】:Django order by integer value, not string value of choices fieldDjango按整数值排序,而不是选择字段的字符串值
【发布时间】:2016-02-11 16:59:43
【问题描述】:

我在使用 Django 选择字段时遇到了一些问题。我编写了代码来计算每个 StudySpace 模型最后 5 个结果的平均评分,并将这些评分存储为字符串,即“忙碌”、“相当忙碌”等。

我能够做到这一点没问题。但是,我希望能够在索引页面中对 StudySpaces 进行排序,但要按它们的平均评级(作为旧整数值)。

我试过了

study_space_list = StudySpace.objects.order_by('avg_rating')

但是当我这样做时,记录按字母顺序排序shown here,而理想情况下,我希望它们使用选择元组中的相应数值进行排序。即忙:1,空:5。

Ratings 模型以及相应的选项如下所示

class Rating(models.Model):
    studyspace = models.ForeignKey(StudySpace, on_delete=models.CASCADE)
    BUSY = 1
    QUITE_BUSY = 2
    AVERAGE = 3
    QUITE_EMPTY = 4
    EMPTY = 5
    rating_choices = (
        (BUSY, 'Busy'),
        (QUITE_BUSY, 'Quite Busy'),
        (AVERAGE, 'Average'),
        (QUITE_EMPTY, 'Quite Empty'),
        (EMPTY, 'Empty'),
    )
    rating = models.IntegerField(choices=rating_choices, default=AVERAGE)

我希望按平均分数排序 StudySpaces 的简化视图如下所示

def index(request):
    study_space_list = StudySpace.objects.order_by(<<<NO CLUE WHAT TO DO HERE>>>)
    context = {'study_space_list': study_space_list}
    return render(request, 'spacefinder/index.html', context)

平均评分由 StudySpace 在每次更新时计算

class StudySpace(models.Model):
    department = models.ForeignKey(Department, on_delete=models.CASCADE)
    space_name = models.CharField(max_length=200, unique=True)
    avg_rating = models.CharField(default='Average', max_length=20)

    def save(self, *args, **kwargs):
        """Recalculates avg_rating on save"""
        query_set = Rating.objects.filter(studyspace=self.id).order_by('-id')[:10]
        if query_set.exists():
            average = query_set.aggregate(Avg('rating')).get('rating__avg')
            self.avg_rating = get_busyness_score(average)
        super(StudySpace, self).save(*args, **kwargs)


def get_busyness_score(value):
    return Rating.rating_choices[round(value)-1][1]

【问题讨论】:

  • 等等,您的平均评分是一个整数(或浮点数),但您将其保存到 CharField?为什么?
  • 我希望能够在我的模板中调用 {{ studyspace.avg_rating }} 并显示人类可读的值。也许这可以通过其他方式完成?

标签: python django


【解决方案1】:

您不应依赖更改数据库数据来适应您希望在模板中显示的方式。如果您对包含整数字符串的CharField 进行排序,它只会按字典顺序排序,这不是您想要的,例如21 小于3,因为3 通过比较第一位数字更大。

解决方案并不难,只需将avg_rating 更改为IntegerField 或更好,DecimalField,它专门用于处理人类可读数字。如果你想在模板中添加一些花哨的东西,你总是可以编写一个自定义模板标签来显示数字周围的额外内容。

阅读有关what is Decimal 的python 文档,并阅读有关如何创建custom template tag 的django 文档。

【讨论】:

    猜你喜欢
    • 2015-12-20
    • 1970-01-01
    • 2012-02-20
    • 2017-03-04
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 2018-07-13
    • 1970-01-01
    相关资源
    最近更新 更多