通过Model的属性(而不是字段)对Django QuerySet进行排序 [英] Sorting a Django QuerySet by a property (not a field) of the Model

查看:659
本文介绍了通过Model的属性(而不是字段)对Django QuerySet进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一些代码和我的目标



我的(简化版)模型:

  class Stop(models.Model):
EXPRESS_STOP = 0
LOCAL_STOP = 1

STOP_TYPES =(
(EXPRESS_STOP,'Express stop'),
(LOCAL_STOP,'Local stop'),


name = models.CharField(max_length = 32)
type = models.PositiveSmallIntegerField(choices = STOP_TYPES)
price = models.DecimalField(max_digits = 5,decimal_places = 2,null = True,blank = True)

def _get_cost(self):
if self.price == 0 :
return 0
elif self.type == self.EXPRESS_STOP:
return self.price / 2
elif self.type == self.LOCAL_STOP:
return self.price * 2
else:
return self.price
cost = property(_get_cost)

我的目标:我想按成本属性排序。我试过两种方法。



使用order_by QuerySet API



 停止。 object.order_by('cost')

导致以下模板错误:

 渲染时捕获FieldError:无法将关键字'cost'解析为字段。 



使用dictionsort模板过滤器



  {%with deal_items | dractionsort:cost_estimateas items_sorted_by_price%} 

收到以下模板错误:

 在呈现时捕获VariableDoesNotExist:在u'Union Square中的关键[cost]查找失败



所以...



我该怎么走关于这样做?

解决方案

使用 QuerySet.extra() 以及 CASE .. 。END 来定义一个新的字段,并对其进行排序。

  Stops.objects.extra select = {'cost':'CASE WHEN price = 0 THEN 0'
'WHEN type =:EXPRESS_STOP THEN price / 2 WHEN type =:LOCAL_STOP THEN price * 2'},
order_by = ['成本'])

QuerySet 从其余部分返回到列表,然后使用 L.sort(key = operator.attrgetter('cost')) / p>

Some code and my goal

My (simplified) model:

class Stop(models.Model):
    EXPRESS_STOP = 0
    LOCAL_STOP   = 1

    STOP_TYPES = (
        (EXPRESS_STOP, 'Express stop'),
        (LOCAL_STOP, 'Local stop'),
    )

    name = models.CharField(max_length=32)
    type = models.PositiveSmallIntegerField(choices=STOP_TYPES)
    price = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True)

    def _get_cost(self):
        if self.price == 0:
            return 0
        elif self.type == self.EXPRESS_STOP:
            return self.price / 2
        elif self.type == self.LOCAL_STOP:
            return self.price * 2
        else:
            return self.price    
    cost = property(_get_cost)

My Goal: I want to sort by the cost property. I tried two approaches.

Using order_by QuerySet API

Stops.objects.order_by('cost')

That yielded the following template error:

Caught FieldError while rendering: Cannot resolve keyword 'cost' into field.

Using dictsort template filter

{% with deal_items|dictsort:"cost_estimate" as items_sorted_by_price %}

Received the following template error:

Caught VariableDoesNotExist while rendering: Failed lookup for key [cost] in u'Union Square'

So...

How should I go about doing this?

解决方案

Use QuerySet.extra() along with CASE ... END to define a new field, and sort on that.

Stops.objects.extra(select={'cost': 'CASE WHEN price=0 THEN 0 '
  'WHEN type=:EXPRESS_STOP THEN price/2 WHEN type=:LOCAL_STOP THEN price*2'},
  order_by=['cost'])

That, or cast the QuerySet returned from the rest to a list, then use L.sort(key=operator.attrgetter('cost')) on it.

这篇关于通过Model的属性(而不是字段)对Django QuerySet进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆