Domanda Django ordina gli articoli in base a due campi, ma li ignora se sono zero


Ho il seguente modello (notevolmente semplificato ai fini di questa domanda):

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)

Per la maggior parte dei prodotti, il prezzo sarà riempito ma il prezzo di vendita non sarà. Quindi, posso ordinare i prodotti in base al prezzo in questo modo:

Product.objects.order_by('price')
Product.objects.order_by('-price')

Tuttavia, alcuni prodotti avranno un prezzo di vendita, e non riesco a trovare un modo per ordinarli in modo ordinato in modo che il prezzo di vendita si intralci con il prezzo normale. Se provo ad ordinare da entrambi i campi:

Product.objects.order_by('sale_price','price')

... poi tutti i prodotti che non sono in vendita appaiono insieme, seguiti da tutto ciò che è, invece di interlacciare i prezzi.

Ha senso ciò? Qualcuno ha un modo per risolvere questo?

Grazie!


15
2018-05-14 10:30


origine


risposte:


È possibile utilizzare il metodo QuerySet extra () per creare un campo aggiuntivo nella query utilizzando la funzione COALESCE in SQL, che restituisce il primo valore non NULL passato.

Product.objects.extra(select={"current_price":"COALESCE(sale_price, price)"}, order_by=["-current_price"])

Devi mettere il tuo order_by nella chiamata extra () come il campo manuale extra "non esiste realmente" per quanto riguarda il resto dell'ORM, ma la sintassi è la stessa dei normali Django order_by () s.

Vedi la documentazione extra () qui: http://docs.djangoproject.com/en/1.3/ref/models/querysets/#extra 


13
2018-05-14 12:59



Se incappi in questo requisito e stai usando Django 1.8 e più in alto, puoi usare django.db.models.functions.Coalesce per una soluzione leggermente più bella, cross db-engine:

from django.db.models.functions import Coalesce

Product.objects.annotate(
    current_price=Coalesce('sale_price', 'price')
).order_by('-current_price')

9
2017-09-29 15:15