58 lines
1.8 KiB
Python
58 lines
1.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
# vi:si:et:sw=4:sts=4:ts=4
|
|
|
|
from django.db.models.sql import Query
|
|
from django.db.models.sql.compiler import SQLCompiler
|
|
from django.db import connections
|
|
import django.db.models.query
|
|
|
|
'''
|
|
models.py:
|
|
-----------------------------------
|
|
from oxdjango.query import QuerySet
|
|
|
|
class Manager(models.Manager):
|
|
def get_query_set(self):
|
|
return QuerySet(self.model)
|
|
|
|
class Model(models.Model):
|
|
...
|
|
objects = Manager()
|
|
'''
|
|
|
|
class NullLastSQLCompiler(SQLCompiler):
|
|
|
|
def get_order_by(self):
|
|
result = super(NullLastSQLCompiler, self).get_order_by()
|
|
if self.query.nulls_last and result \
|
|
and self.connection.vendor == 'postgresql':
|
|
return [(expr, (sql + ' NULLS LAST', params, is_ref))
|
|
for (expr, (sql, params, is_ref)) in result]
|
|
return result
|
|
|
|
class NullsLastQuery(Query):
|
|
nulls_last = False
|
|
|
|
def clone(self, *args, **kwargs):
|
|
obj = super(NullsLastQuery, self).clone(*args, **kwargs)
|
|
obj.nulls_last = self.nulls_last
|
|
return obj
|
|
|
|
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]
|
|
return NullLastSQLCompiler(self, connection, using)
|
|
|
|
class QuerySet(django.db.models.query.QuerySet):
|
|
|
|
def __init__(self, model=None, query=None, using=None, **kwargs):
|
|
super(QuerySet, self).__init__(model=model, query=query, using=None, **kwargs)
|
|
self.query = query or NullsLastQuery(self.model)
|
|
|
|
def order_by(self, *args, **kwargs):
|
|
nulls_last = kwargs.pop('nulls_last', False)
|
|
obj = super(QuerySet, self).order_by(*args, **kwargs)
|
|
obj.query.nulls_last = nulls_last
|
|
return obj
|