Django:在查询中添加“NULLS LAST”
我想用Postgresql的“NULLS LAST”选项来对一个模型进行排序。请问该怎么做呢?
我试过这样写:
MyModel.objects.all().extra(order_by=('-price', 'NULLS LAST'))
但是我得到了这个错误:
“无法将关键字'NULLS LAST'解析为字段”
8 个回答
23
如果你想让这个过程变得透明,并且适用于所有列,你可以重新定义 SQL 的生成方式。为此,你需要创建一个自己的管理器,这样它就可以返回你自定义的查询集(QuerySet),进而返回你自定义的查询(Query),以便使用自定义的编译器(Compiler)。我在 Django 1.5 中的代码大致是这样的:
from django.db import models, connections
class NullsLastQuery(models.sql.query.Query):
"""
Query that uses custom compiler,
to utilize PostgreSQL feature of setting position of NULL records
"""
def get_compiler(self, using=None, connection=None):
if using is None and connection is None:
raise ValueError("Need either using or connection")
if using:
connection = connections[using]
# defining that class elsewhere results in import errors
from django.db.models.sql.compiler import SQLCompiler
class NullsLastSQLCompiler(SQLCompiler):
def get_ordering(self):
result, group_by = super(NullsLastSQLCompiler, self
).get_ordering()
if self.connection.vendor == 'postgresql' and result:
result = [line + " NULLS LAST" for line in result]
return result, group_by
return NullsLastSQLCompiler(self, connection, using)
class NullsLastQuerySet(models.query.QuerySet):
def __init__(self, model=None, query=None, using=None):
super(NullsLastQuerySet, self).__init__(model, query, using)
self.query = query or NullsLastQuery(self.model)
class NullsLastManager(models.Manager):
def get_query_set(self):
return NullsLastQuerySet(self.model, using=self._db)
class YourModel(models.Model):
objects = NullsLastManager()
24
我找到的最接近的做法是分两步来处理。第一步是先按照有值的字段排序,然后再处理空值:
all_projects = Project.objects.select_related().filter(
company=company).order_by('-date_due')
q = all_projects.extra(select={'date_due_null': 'date_due is null'})
q = q.extra(order_by=['date_due_null'])
print q.query
注意:请留意关于extra()
的警告,它可能在未来被弃用。
205
from django.db.models import F
MyModel.objects.all().order_by(F('price').desc(nulls_last=True))
这个功能是在Django 1.11版本中新增的。
https://docs.djangoproject.com/en/dev/releases/1.11/
新增了nulls_first和nulls_last这两个参数,可以用来控制空值的排序。
关于Django 3.1的参考资料:https://docs.djangoproject.com/en/3.1/ref/models/expressions/#using-f-to-sort-null-values