Order a set of Django requests in ascending order, but with 0-digit elements at the end

I am new to python, django. What I'm trying to do is that I have a model defined as products that has two columns: name and price.

name    price
pen      20
paper    30
eraser   0

I am trying to sort them using the following code:

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

This sorts the values ​​as 0,20,30.

Model code

class Product(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)
    price = models.IntegerField('Price', blank=True, null=True)

What I'm trying to achieve is to sort it as 20,30,0with the addition of 0 at the end.

Is there any function with which I can achieve it?

+4
source share
4 answers

, . :

Product.objects.all().order_by(\
        Case(When(price=0, then=Value(MAX_INT)), default=F('price')))

MAX_INT=2147483647 - 32- , Django DB.

+6

, , , , Python ( )

qs = Product.objects.exclude(price=0).order_by('-price') | Product.objects.filter(price=0)
+4

, SQL-:

SELECT * FROM product ORDER BY price = 0, price;

Django ORM extra() :

Product.objects.extra(select={"custom":"price = 0"}, order_by=["custom","price"]).all()
+1

Conditional expressions allow you to use if ... elif ... else in filters, annotations, aggregates, and updates. The conditional expression evaluates a number of conditions for each row of the table and returns the expression of the matching result.

from django.db.models import IntegerField, Case, Value, When

MAX_INT = 2147483647
Product.objects.annotate(
    my_price=Case(
        When(price=0, then=Value(MAX_INT)),
        default='price',
        output_field=IntegerField(),
    )
).order_by('my_price')

Edited: Fix bug in @ivan's answer and comment.

+1
source

Source: https://habr.com/ru/post/1612413/


All Articles