【问题标题】:Django order_by a propertyDjango order_by 一个属性
【发布时间】:2013-04-25 17:00:24
【问题描述】:

我遇到了一个问题,我试图创建一个查询集,其结果不是按模型上的字段排序,而是按模型上的方法返回的值的结果排序。

也就是说:

class MyModel(models.Model):

someAttributes = models.TextField(blank=True)

@property
def calculate_rating(self):
<do some calculation and return integer>

鉴于此,我如何构造一个 QuerySet,按由 calculate_rating() 返回的每个实例的值对结果进行排序?

在尝试简单地使用 order_by() 时,我收到一个错误:

无法将关键字“average_rating”解析为字段。

谁能提供一些想法?

【问题讨论】:

标签: django django-models


【解决方案1】:

order_by 用于数据库内容。尝试改用sorted

sorted(MyModel.objects.all(),  key=lambda m: m.calculate_rating)

【讨论】:

    【解决方案2】:

    没有办法做到这一点。您可以做的一件事是为该模型创建一个单独的数据库字段并将计算的评分保存在其中。您可能可以覆盖模型的保存方法并在那里进行计算,之后您只能引用该值。

    您还可以使用Python sorted 对返回的QuerySet 进行排序。考虑到使用内置 sorted 函数的排序方法会大大增加计算复杂度,在生产中使用此类代码并不是一个好主意。

    更多信息你可以查看这个答案:https://stackoverflow.com/a/981802/1869597

    【讨论】:

      【解决方案3】:

      实现您想要的最佳方式是使用CaseWhen 语句。这允许您将最终结果保存在 QuerySet 而不是列表中;)

      ratings_tuples = [(r.id, r.calc_rating) for r in MyModel.objects.all()]  
      ratings_list = sorted(ratings_tuples, key = lambda x: x[1])  # Sort by second tuple elem
      

      这是我们的排序列表ratings_list,它以排序方式保存元素的 ID 和评级

      pk_list = [idx for idx, rating in ratings_list]  
      from django.db.models import Case, When
      preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)])  
      queryset = MyModel.objects.filter(pk__in=pk_list).order_by(preserved)  
      

      现在,使用CaseWhen 语句,我们可以根据已有列表中的ID 对查询集进行排序。 (Django Docs for details)。
      有类似的情况,需要一个解决方案。所以在https://stackoverflow.com/a/37648265/4271452这个帖子上找到了一些细节,它的工作原理。

      【讨论】:

      • 不错!与sorted 相比,这里发生的事情不太清楚,但在很多情况下,有必要将结果保留为查询集。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 2011-01-11
      • 2014-06-20
      • 1970-01-01
      • 2010-11-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多