Django ordena elementos por dos campos, pero los ignora si son cero
Tengo el siguiente modelo (muy simplificado para los propósitos de esta pregunta):
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)
Para la mayoría de los productos, se completará el precio, pero no el precio_venta. Entonces, puedo ordenar productos por precio así:
Product.objects.order_by('price')
Product.objects.order_by('-price')
Sin embargo, algunos productos tendrán un precio de oferta y no puedo encontrar una manera de ordenarlos de manera ordenada para que el precio de oferta se intercale con el precio normal. Si intento ordenar por ambos campos:
Product.objects.order_by('sale_price','price')
...luego aparecen juntos todos los productos que no están en oferta, seguidos de todos los que sí, en lugar de intercalar los precios.
¿Esto tiene sentido? ¿Alguien tiene una manera de resolver esto?
¡Gracias!
Si te topas con este requisito y estás usando Django 1.8 y superior, puedes usar django.db.models.functions.Coalesce
una solución ligeramente mejor, entre motores de base de datos:
from django.db.models.functions import Coalesce
Product.objects.annotate(
current_price=Coalesce('sale_price', 'price')
).order_by('-current_price')
Puede usar el método QuerySet extra() para crear un campo adicional en su consulta usando la función COALESCE en SQL, que devuelve el primer valor no NULL que se pasa.
Product.objects.extra(select={"current_price":"COALESCE(sale_price, price)"}, order_by=["-current_price"])
Tienes que poner tu order_by en la llamada extra() ya que el campo manual adicional "realmente no existe" en lo que respecta al resto del ORM, pero la sintaxis es la misma que la de los order_by() normales de Django.
Consulte la documentación extra() aquí: http://docs.djangoproject.com/en/1.3/ref/models/querysets/#extra