diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py index 5760b59098..c2b92ecdee 100644 --- a/django/db/backends/base/features.py +++ b/django/db/backends/base/features.py @@ -91,6 +91,9 @@ class BaseDatabaseFeatures: # Does the backend support NULLS FIRST and NULLS LAST in ORDER BY? supports_order_by_nulls_modifier = True + # Does the backend orders NULLS FIRST by default? + order_by_nulls_first = False + # The database's limit on the number of query parameters. max_query_params = None diff --git a/django/db/backends/mysql/features.py b/django/db/backends/mysql/features.py index 1d0cd365db..e1d4ce726b 100644 --- a/django/db/backends/mysql/features.py +++ b/django/db/backends/mysql/features.py @@ -51,6 +51,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): # Neither MySQL nor MariaDB support partial indexes. supports_partial_indexes = False supports_order_by_nulls_modifier = False + order_by_nulls_first = True @cached_property def _mysql_storage_engine(self): diff --git a/django/db/backends/sqlite3/features.py b/django/db/backends/sqlite3/features.py index 6aebbc3262..84eca98644 100644 --- a/django/db/backends/sqlite3/features.py +++ b/django/db/backends/sqlite3/features.py @@ -45,3 +45,4 @@ class DatabaseFeatures(BaseDatabaseFeatures): supports_frame_range_fixed_distance = Database.sqlite_version_info >= (3, 28, 0) supports_aggregate_filter_clause = Database.sqlite_version_info >= (3, 30, 1) supports_order_by_nulls_modifier = Database.sqlite_version_info >= (3, 30, 0) + order_by_nulls_first = True diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index f773e99a0f..84960d77e1 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -1120,9 +1120,13 @@ class OrderBy(BaseExpression): elif self.nulls_first: template = '%s NULLS FIRST' % template else: - if self.nulls_last: + if self.nulls_last and not ( + self.descending and connection.features.order_by_nulls_first + ): template = '%%(expression)s IS NULL, %s' % template - elif self.nulls_first: + elif self.nulls_first and not ( + not self.descending and connection.features.order_by_nulls_first + ): template = '%%(expression)s IS NOT NULL, %s' % template connection.ops.check_expression_support(self) expression_sql, params = compiler.compile(self.expression)