Ben*_*Ben 16 django sql-order-by django-orm
我有以下模型(为了这个问题的目的大大简化):
class Product(models.Model):
price = models.DecimalField(max_digits=8, decimal_places=2)
sale_price = models.DecimalField(max_digits=10, blank=True, null=True, decimal_places=2)
Run Code Online (Sandbox Code Playgroud)
对于大多数产品,价格将被填补,但sale_price将不会.所以,我可以按价格订购产品:
Product.objects.order_by('price')
Product.objects.order_by('-price')
Run Code Online (Sandbox Code Playgroud)
但是,有些产品会有sale_price,我找不到一种方法来整齐地订购这些产品,以便销售价格与正常价格交错.如果我尝试按两个字段排序:
Product.objects.order_by('sale_price','price')
Run Code Online (Sandbox Code Playgroud)
...然后,所有未售出的产品一起显示,然后是所有产品,而不是交叉价格.
这有意义吗?有没有人有办法解决这个问题?
谢谢!
小智 13
您可以使用extra()QuerySet方法在SQL中使用COALESCE函数在查询中创建一个额外的字段,该函数返回它传递的第一个非NULL值.
Product.objects.extra(select={"current_price":"COALESCE(sale_price, price)"}, order_by=["-current_price"])
Run Code Online (Sandbox Code Playgroud)
您必须将order_by放在extra()调用中,因为就ORM的其余部分而言,额外的手动字段"实际上并不存在",但语法与普通的Django order_by()s相同.
请参阅此处的extra()文档:http://docs.djangoproject.com/en/1.3/ref/models/querysets/#extra
tut*_*uju 13
如果您偶然发现这个要求并碰巧使用Django 1.8及更高版本,您可以使用django.db.models.functions.Coalesce更好的交叉数据库引擎解决方案:
from django.db.models.functions import Coalesce
Product.objects.annotate(
current_price=Coalesce('sale_price', 'price')
).order_by('-current_price')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12654 次 |
| 最近记录: |