Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django "NULLS LAST" for creating Indexes

Django 1.11 and later allow using F-expressions for adding nulls last option to queries:

queryset = Person.objects.all().order_by(F('wealth').desc(nulls_last=True))

However, we want to use this functionality for creating Indexes. A standard Django Index inside a model definition:

indexes = [
        models.Index(fields=['-wealth']),
]

I tried something along the lines of:

indexes = [
        models.Index(fields=[models.F('wealth').desc(nulls_last=True)]),
]

which returns AttributeError: 'OrderBy' object has no attribute 'startswith'.

Is this possible to do using F-expressions in Django?

like image 343
Vidak Avatar asked Mar 26 '18 14:03

Vidak


2 Answers

No, unfortunately, that is currently (Django <=2.1) not possible. If you look at the source of models.Index, you will see that it assumes that the argument fields contains model names and nothing else.

As a workaround, you could manually create your index with raw SQL in a migration.

like image 92
Daniel Hepper Avatar answered Sep 29 '22 00:09

Daniel Hepper


Fortunately it is now possible to create functional indexes since Django 3.2. The example which you posted has to be adjusted a little by moving the field from fields to *expressions and by adding a name, which is required when using expressions.

indexes = [
    Index(F('wealth').desc(nulls_last=True), name='wealth_desc_idx'),
]

https://docs.djangoproject.com/en/3.2/ref/models/indexes/#expressions

like image 44
paffer Avatar answered Sep 28 '22 23:09

paffer