我在使用Django选择字段时遇到了一些麻烦。我编写了代码来计算每个StudySpace模型的最后5个结果的平均评分,并将这些评级存储为字符串,即"忙碌","相当繁忙"等等。
我能做到这一点没问题。但是,我希望能够在索引页面中对StudySpaces进行排序,但是要按其平均评级(作为旧的整数值)进行排序。
我已经尝试了
study_space_list = StudySpace.objects.order_by('avg_rating')
但是当我这样做时,这些记录按字母顺序排序shown here,而理想情况下我希望它们使用选择元组中的相应数值进行排序。即忙:1,空:5。
评级模型以及相应的选择如下
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]
答案 0 :(得分:1)
您不应该依赖于更改数据库数据以适应您希望在模板中显示的方式。如果您对包含整数字符串的CharField
进行排序,则它只会按字典顺序排序,这不是您想要的,因为21
小于3
,因为3
通过比较第一个数字来增大。
解决方案并不难,只需将avg_rating
更改为IntegerField
或更好,DecimalField
,专门处理人类可读数字。如果你想在模板中添加一些花哨的东西,你总是可以编写一个自定义模板标签来显示数字周围的额外内容。
阅读关于what is Decimal的python doc,并阅读有关如何创建custom template tag的django doc。