From 0920486c9a9ff9a6a08f4673105e042572c00614 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Sat, 14 Dec 2024 15:21:24 -0500 Subject: [PATCH 1/5] Update to Django 5.2 - Adapt SQLDeleteCompiler.execute_sql() per https://github.com/django/django/commit/ddefc3fed1cf1f0d3fab455babbbc009b76e4196 - Remove special-casing of DecimalField calling adapt_decimalfield_value() obsoleted by https://github.com/django/django/commit/1860a1afc9ac20750f932e8e0a94b32d096f2848 - Add ExpressionList.as_mql() for https://github.com/django/django/commit/d99985bbc121749c5a6bb9eb9a4a9099b6a002eb --- .evergreen/run-tests.sh | 2 +- .github/workflows/test-python.yml | 2 +- README.md | 10 +++--- django_mongodb_backend/__init__.py | 2 +- django_mongodb_backend/compiler.py | 8 ++--- django_mongodb_backend/expressions.py | 4 +++ django_mongodb_backend/features.py | 40 +++++++++++++++++++++++ django_mongodb_backend/fields/array.py | 6 +--- django_mongodb_backend/lookups.py | 7 ++-- django_mongodb_backend/operations.py | 22 ------------- django_mongodb_backend/query_utils.py | 5 +-- docs/source/conf.py | 4 +-- docs/source/index.rst | 2 +- docs/source/intro/configure.rst | 8 ++--- docs/source/intro/install.rst | 4 +-- docs/source/releases/5.1.x.rst | 2 ++ docs/source/releases/5.2.x.rst | 14 ++++++++ docs/source/releases/index.rst | 3 +- docs/source/topics/known-issues.rst | 1 + pyproject.toml | 2 +- requirements.txt | 2 +- tests/indexes_/test_condition.py | 2 +- tests/model_forms_/test_embedded_model.py | 8 ++--- 23 files changed, 95 insertions(+), 65 deletions(-) create mode 100644 docs/source/releases/5.2.x.rst diff --git a/.evergreen/run-tests.sh b/.evergreen/run-tests.sh index f383a71a9..f49a0e9a9 100644 --- a/.evergreen/run-tests.sh +++ b/.evergreen/run-tests.sh @@ -9,7 +9,7 @@ python -m pip install -U pip pip install -e . # Install django and test dependencies -git clone --branch mongodb-5.1.x https://github.com/mongodb-forks/django django_repo +git clone --branch mongodb-5.2.x https://github.com/mongodb-forks/django django_repo pushd django_repo/tests/ pip install -e .. pip install -r requirements/py3.txt diff --git a/.github/workflows/test-python.yml b/.github/workflows/test-python.yml index cc791d553..d471f3f21 100644 --- a/.github/workflows/test-python.yml +++ b/.github/workflows/test-python.yml @@ -33,7 +33,7 @@ jobs: uses: actions/checkout@v4 with: repository: 'mongodb-forks/django' - ref: 'mongodb-5.1.x' + ref: 'mongodb-5.2.x' path: 'django_repo' persist-credentials: false - name: Install system packages for Django's Python test dependencies diff --git a/README.md b/README.md index 15902c866..fc97565fa 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ https://django-mongodb-backend.readthedocs.io/en/latest/. ## Install Use the version of `django-mongodb-backend` that corresponds to your version of -Django. For example, to get the latest compatible release for Django 5.1.x: +Django. For example, to get the latest compatible release for Django 5.2.x: ```bash -pip install --pre django-mongodb-backend==5.1.* +pip install --pre django-mongodb-backend==5.2.* ``` (Until the package is out of beta, you must use pip's `--pre` option.) @@ -36,11 +36,11 @@ You can check what version of Django you're using with: django-admin --version ``` -The snippet below specifies `5.1.x.zip` at the end of -the template url to get the template for any Django version matching 5.1: +The snippet below specifies `5.2.x.zip` at the end of +the template url to get the template for any Django version matching 5.2: ```bash -django-admin startproject example --template https://github.com/mongodb-labs/django-mongodb-project/archive/refs/heads/5.1.x.zip +django-admin startproject example --template https://github.com/mongodb-labs/django-mongodb-project/archive/refs/heads/5.2.x.zip ``` diff --git a/django_mongodb_backend/__init__.py b/django_mongodb_backend/__init__.py index bc2eb46f6..65b819b2a 100644 --- a/django_mongodb_backend/__init__.py +++ b/django_mongodb_backend/__init__.py @@ -1,4 +1,4 @@ -__version__ = "5.1.0b3.dev0" +__version__ = "5.2.0b0.dev0" # Check Django compatibility before other imports which may fail if the # wrong version of Django is installed. diff --git a/django_mongodb_backend/compiler.py b/django_mongodb_backend/compiler.py index cf666619a..2dbb9eca8 100644 --- a/django_mongodb_backend/compiler.py +++ b/django_mongodb_backend/compiler.py @@ -17,7 +17,6 @@ from django.utils.functional import cached_property from pymongo import ASCENDING, DESCENDING -from .base import Cursor from .query import MongoQuery, wrap_database_errors @@ -690,15 +689,12 @@ def collection_name(self): class SQLDeleteCompiler(compiler.SQLDeleteCompiler, SQLCompiler): def execute_sql(self, result_type=MULTI): - cursor = Cursor() try: query = self.build_query() except EmptyResultSet: - rowcount = 0 + return 0 else: - rowcount = query.delete() - cursor.rowcount = rowcount - return cursor + return query.delete() def check_query(self): super().check_query() diff --git a/django_mongodb_backend/expressions.py b/django_mongodb_backend/expressions.py index 8e8c18154..f7fcdae8f 100644 --- a/django_mongodb_backend/expressions.py +++ b/django_mongodb_backend/expressions.py @@ -10,6 +10,7 @@ Col, CombinedExpression, Exists, + ExpressionList, ExpressionWrapper, F, NegatedExpression, @@ -24,6 +25,8 @@ ) from django.db.models.sql import Query +from .query_utils import process_lhs + def case(self, compiler, connection): case_parts = [] @@ -202,6 +205,7 @@ def register_expressions(): Col.as_mql = col CombinedExpression.as_mql = combined_expression Exists.as_mql = exists + ExpressionList.as_mql = process_lhs ExpressionWrapper.as_mql = expression_wrapper F.as_mql = f NegatedExpression.as_mql = negated_expression diff --git a/django_mongodb_backend/features.py b/django_mongodb_backend/features.py index a286a2cbf..94711de96 100644 --- a/django_mongodb_backend/features.py +++ b/django_mongodb_backend/features.py @@ -88,6 +88,34 @@ class DatabaseFeatures(BaseDatabaseFeatures): # of $setIsSubset must be arrays. Second argument is of type: null" # https://jira.mongodb.org/browse/SERVER-99186 "model_fields_.test_arrayfield.QueryingTests.test_contained_by_subquery", + # Broken by https://github.com/django/django/commit/65ad4ade74dc9208b9d686a451cd6045df0c9c3a + "aggregation.tests.AggregateTestCase.test_even_more_aggregate", + "aggregation.tests.AggregateTestCase.test_grouped_annotation_in_group_by", + "aggregation.tests.AggregateTestCase.test_non_grouped_annotation_not_in_group_by", + "aggregation_regress.tests.AggregationTests.test_aggregate_fexpr", + "aggregation_regress.tests.AggregationTests.test_values_list_annotation_args_ordering", + "annotations.tests.NonAggregateAnnotationTestCase.test_annotation_subquery_and_aggregate_values_chaining", + "annotations.tests.NonAggregateAnnotationTestCase.test_values_fields_annotations_order", + "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_multiple_models_with_values_and_datetime_annotations", + "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_multiple_models_with_values_list_and_datetime_annotations", + "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_multiple_models_with_values_list_and_annotations", + "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_with_field_and_annotation_values", + "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_with_two_annotated_values_list", + "queries.tests.Queries1Tests.test_union_values_subquery", + # JSONArray not implemented. + "db_functions.json.test_json_array.JSONArrayTests", + # Some usage of prefetch_related() raises "ColPairs is not supported." + "known_related_objects.tests.ExistingRelatedInstancesTests.test_one_to_one_multi_prefetch_related", + "known_related_objects.tests.ExistingRelatedInstancesTests.test_one_to_one_prefetch_related", + "prefetch_related.tests.DeprecationTests.test_prefetch_one_level_fallback", + "prefetch_related.tests.MultiDbTests.test_using_is_honored_fkey", + "prefetch_related.tests.MultiDbTests.test_using_is_honored_inheritance", + "prefetch_related.tests.NestedPrefetchTests.test_nested_prefetch_is_not_overwritten_by_related_object", + "prefetch_related.tests.NullableTest.test_prefetch_nullable", + "prefetch_related.tests.Ticket19607Tests.test_bug", + # Value.as_mql() doesn't call output_field.get_db_prep_save(): + # https://github.com/mongodb/django-mongodb-backend/issues/282 + "model_fields.test_jsonfield.TestSaveLoad.test_bulk_update_custom_get_prep_value", } # $bitAnd, #bitOr, and $bitXor are new in MongoDB 6.3. _django_test_expected_failures_bitwise = { @@ -112,6 +140,7 @@ def django_test_expected_failures(self): # bson.errors.InvalidDocument: cannot encode object: # `. + +Regarding new features in Django 5.2, +:class:`~django.db.models.CompositePrimaryKey` isn't supported. diff --git a/docs/source/releases/index.rst b/docs/source/releases/index.rst index b2649eed2..bc14e221e 100644 --- a/docs/source/releases/index.rst +++ b/docs/source/releases/index.rst @@ -5,11 +5,12 @@ Release notes The release notes will tell you what's new in each version and will also describe any backwards-incompatible changes. -Below are release notes through Django MongoDB backend 5.1.x. Newer versions of +Below are release notes through Django MongoDB backend 5.2.x. Newer versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 5.2.x 5.1.x 5.0.x diff --git a/docs/source/topics/known-issues.rst b/docs/source/topics/known-issues.rst index 2bf668075..4b34fecfd 100644 --- a/docs/source/topics/known-issues.rst +++ b/docs/source/topics/known-issues.rst @@ -23,6 +23,7 @@ Model fields - :class:`~django.db.models.AutoField` (including :class:`~django.db.models.BigAutoField` and :class:`~django.db.models.SmallAutoField`) + - :class:`~django.db.models.CompositePrimaryKey` - :class:`~django.db.models.GeneratedField` Querying diff --git a/pyproject.toml b/pyproject.toml index 241874fd5..7b412e1db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,7 @@ keywords = [ classifiers = [ "Development Status :: 4 - Beta", "Framework :: Django", - "Framework :: Django :: 5.1", + "Framework :: Django :: 5.2", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: OS Independent", diff --git a/requirements.txt b/requirements.txt index 04dc753dd..5f081ffd7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -django>=5.1,<5.2 +django>=5.2,<6.0 pymongo>=4.6,<5.0 diff --git a/tests/indexes_/test_condition.py b/tests/indexes_/test_condition.py index 5077dd0bd..3c49f1ec3 100644 --- a/tests/indexes_/test_condition.py +++ b/tests/indexes_/test_condition.py @@ -78,7 +78,7 @@ def test_composite_index(self): { "$and": [ {"number": {"$gte": 3}}, - {"$or": [{"body": {"$gt": "test1"}}, {"body": {"$in": ["A", "B"]}}]}, + {"$or": [{"body": {"$gt": "test1"}}, {"body": {"$in": ("A", "B")}}]}, ] }, ) diff --git a/tests/model_forms_/test_embedded_model.py b/tests/model_forms_/test_embedded_model.py index 4447b59f2..d5eb71eaf 100644 --- a/tests/model_forms_/test_embedded_model.py +++ b/tests/model_forms_/test_embedded_model.py @@ -182,9 +182,9 @@ def test_some_missing_data(self): required id="id_title">
-
+
Publisher: -
    +
    • Enter all required values.
    @@ -252,9 +252,9 @@ def test_invalid_field_data(self): maxlength="50" required id="id_title">
    -
    +
    Publisher: -
      +
      • Ensure this value has at most 2 characters (it has 8).
      From f15c8a30e81d98278220ebd4e0c3dea5a01cff3c Mon Sep 17 00:00:00 2001 From: Emanuel Lupi Date: Sat, 21 Dec 2024 00:31:47 -0300 Subject: [PATCH 2/5] Fix columns order in aggregation queries Adapt for a change in Django 5.2: https://github.com/django/django/commit/65ad4ade74dc9208b9d686a451cd6045df0c9c3a --- django_mongodb_backend/compiler.py | 39 ++++++++++++++++++--------- django_mongodb_backend/expressions.py | 6 ++++- django_mongodb_backend/features.py | 14 ---------- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/django_mongodb_backend/compiler.py b/django_mongodb_backend/compiler.py index 2dbb9eca8..66154902e 100644 --- a/django_mongodb_backend/compiler.py +++ b/django_mongodb_backend/compiler.py @@ -402,12 +402,6 @@ def columns(self): columns = ( self.get_default_columns(select_mask) if self.query.default_cols else self.query.select ) - # Populate QuerySet.select_related() data. - related_columns = [] - if self.query.select_related: - self.get_related_selections(related_columns, select_mask) - if related_columns: - related_columns, _ = zip(*related_columns, strict=True) annotation_idx = 1 @@ -426,11 +420,28 @@ def project_field(column): annotation_idx += 1 return target, column - return ( - tuple(map(project_field, columns)) - + tuple(self.annotations.items()) - + tuple(map(project_field, related_columns)) - ) + selected = [] + if self.query.selected is None: + selected = [ + *(project_field(col) for col in columns), + *self.annotations.items(), + ] + else: + for expression in self.query.selected.values(): + # Reference to an annotation. + if isinstance(expression, str): + alias, expression = expression, self.annotations[expression] + # Reference to a column. + elif isinstance(expression, int): + alias, expression = project_field(columns[expression]) + selected.append((alias, expression)) + # Populate QuerySet.select_related() data. + related_columns = [] + if self.query.select_related: + self.get_related_selections(related_columns, select_mask) + if related_columns: + related_columns, _ = zip(*related_columns, strict=True) + return tuple(selected) + tuple(map(project_field, related_columns)) @cached_property def base_table(self): @@ -477,7 +488,11 @@ def get_combinator_queries(self): # If the columns list is limited, then all combined queries # must have the same columns list. Set the selects defined on # the query on all combined queries, if not already set. - if not compiler_.query.values_select and self.query.values_select: + selected = self.query.selected + if selected is not None and compiler_.query.selected is None: + compiler_.query = compiler_.query.clone() + compiler_.query.set_values(selected) + elif not compiler_.query.values_select and self.query.values_select: compiler_.query = compiler_.query.clone() compiler_.query.set_values( ( diff --git a/django_mongodb_backend/expressions.py b/django_mongodb_backend/expressions.py index f7fcdae8f..926e5781f 100644 --- a/django_mongodb_backend/expressions.py +++ b/django_mongodb_backend/expressions.py @@ -153,7 +153,11 @@ def ref(self, compiler, connection): # noqa: ARG001 if isinstance(self.source, Col) and self.source.alias != compiler.collection_name else "" ) - return f"${prefix}{self.refs}" + if hasattr(self, "ordinal"): + refs, _ = compiler.columns[self.ordinal - 1] + else: + refs = self.refs + return f"${prefix}{refs}" def star(self, compiler, connection): # noqa: ARG001 diff --git a/django_mongodb_backend/features.py b/django_mongodb_backend/features.py index 94711de96..3639eb1cd 100644 --- a/django_mongodb_backend/features.py +++ b/django_mongodb_backend/features.py @@ -88,20 +88,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): # of $setIsSubset must be arrays. Second argument is of type: null" # https://jira.mongodb.org/browse/SERVER-99186 "model_fields_.test_arrayfield.QueryingTests.test_contained_by_subquery", - # Broken by https://github.com/django/django/commit/65ad4ade74dc9208b9d686a451cd6045df0c9c3a - "aggregation.tests.AggregateTestCase.test_even_more_aggregate", - "aggregation.tests.AggregateTestCase.test_grouped_annotation_in_group_by", - "aggregation.tests.AggregateTestCase.test_non_grouped_annotation_not_in_group_by", - "aggregation_regress.tests.AggregationTests.test_aggregate_fexpr", - "aggregation_regress.tests.AggregationTests.test_values_list_annotation_args_ordering", - "annotations.tests.NonAggregateAnnotationTestCase.test_annotation_subquery_and_aggregate_values_chaining", - "annotations.tests.NonAggregateAnnotationTestCase.test_values_fields_annotations_order", - "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_multiple_models_with_values_and_datetime_annotations", - "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_multiple_models_with_values_list_and_datetime_annotations", - "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_multiple_models_with_values_list_and_annotations", - "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_with_field_and_annotation_values", - "queries.test_qs_combinators.QuerySetSetOperationTests.test_union_with_two_annotated_values_list", - "queries.tests.Queries1Tests.test_union_values_subquery", # JSONArray not implemented. "db_functions.json.test_json_array.JSONArrayTests", # Some usage of prefetch_related() raises "ColPairs is not supported." From 8278cbd1bb301dea6333387cc8176a00484a3610 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Sat, 5 Apr 2025 22:26:45 -0400 Subject: [PATCH 3/5] Implement ColPairs.as_mql() to fix regression in some prefetch_related() Adapt for Django 5.2 which introduced ColPairs. --- django_mongodb_backend/expressions.py | 9 +++++++++ django_mongodb_backend/features.py | 9 --------- django_mongodb_backend/lookups.py | 3 --- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/django_mongodb_backend/expressions.py b/django_mongodb_backend/expressions.py index 926e5781f..b8fbebf52 100644 --- a/django_mongodb_backend/expressions.py +++ b/django_mongodb_backend/expressions.py @@ -8,6 +8,7 @@ from django.db.models.expressions import ( Case, Col, + ColPairs, CombinedExpression, Exists, ExpressionList, @@ -74,6 +75,13 @@ def col(self, compiler, connection): # noqa: ARG001 return f"${prefix}{self.target.column}" +def col_pairs(self, compiler, connection): + cols = self.get_cols() + if len(cols) > 1: + raise NotSupportedError("ColPairs is not supported.") + return cols[0].as_mql(compiler, connection) + + def combined_expression(self, compiler, connection): expressions = [ self.lhs.as_mql(compiler, connection), @@ -207,6 +215,7 @@ def value(self, compiler, connection): # noqa: ARG001 def register_expressions(): Case.as_mql = case Col.as_mql = col + ColPairs.as_mql = col_pairs CombinedExpression.as_mql = combined_expression Exists.as_mql = exists ExpressionList.as_mql = process_lhs diff --git a/django_mongodb_backend/features.py b/django_mongodb_backend/features.py index 3639eb1cd..77b21210c 100644 --- a/django_mongodb_backend/features.py +++ b/django_mongodb_backend/features.py @@ -90,15 +90,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): "model_fields_.test_arrayfield.QueryingTests.test_contained_by_subquery", # JSONArray not implemented. "db_functions.json.test_json_array.JSONArrayTests", - # Some usage of prefetch_related() raises "ColPairs is not supported." - "known_related_objects.tests.ExistingRelatedInstancesTests.test_one_to_one_multi_prefetch_related", - "known_related_objects.tests.ExistingRelatedInstancesTests.test_one_to_one_prefetch_related", - "prefetch_related.tests.DeprecationTests.test_prefetch_one_level_fallback", - "prefetch_related.tests.MultiDbTests.test_using_is_honored_fkey", - "prefetch_related.tests.MultiDbTests.test_using_is_honored_inheritance", - "prefetch_related.tests.NestedPrefetchTests.test_nested_prefetch_is_not_overwritten_by_related_object", - "prefetch_related.tests.NullableTest.test_prefetch_nullable", - "prefetch_related.tests.Ticket19607Tests.test_bug", # Value.as_mql() doesn't call output_field.get_db_prep_save(): # https://github.com/mongodb/django-mongodb-backend/issues/282 "model_fields.test_jsonfield.TestSaveLoad.test_bulk_update_custom_get_prep_value", diff --git a/django_mongodb_backend/lookups.py b/django_mongodb_backend/lookups.py index 58805b7c8..8dda2bab3 100644 --- a/django_mongodb_backend/lookups.py +++ b/django_mongodb_backend/lookups.py @@ -1,5 +1,4 @@ from django.db import NotSupportedError -from django.db.models.expressions import ColPairs from django.db.models.fields.related_lookups import In, RelatedIn from django.db.models.lookups import ( BuiltinLookup, @@ -35,8 +34,6 @@ def field_resolve_expression_parameter(self, compiler, connection, sql, param): def in_(self, compiler, connection): - if isinstance(self.lhs, ColPairs): - raise NotImplementedError("ColPairs is not supported.") db_rhs = getattr(self.rhs, "_db", None) if db_rhs is not None and db_rhs != connection.alias: raise ValueError( From c71bc662eaab4f532e1fe10e672bbc632d621fb4 Mon Sep 17 00:00:00 2001 From: Emanuel Lupi Date: Tue, 18 Mar 2025 00:47:16 -0300 Subject: [PATCH 4/5] Add support for JSONArray function --- django_mongodb_backend/features.py | 2 -- django_mongodb_backend/functions.py | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/django_mongodb_backend/features.py b/django_mongodb_backend/features.py index 77b21210c..82c358803 100644 --- a/django_mongodb_backend/features.py +++ b/django_mongodb_backend/features.py @@ -88,8 +88,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): # of $setIsSubset must be arrays. Second argument is of type: null" # https://jira.mongodb.org/browse/SERVER-99186 "model_fields_.test_arrayfield.QueryingTests.test_contained_by_subquery", - # JSONArray not implemented. - "db_functions.json.test_json_array.JSONArrayTests", # Value.as_mql() doesn't call output_field.get_db_prep_save(): # https://github.com/mongodb/django-mongodb-backend/issues/282 "model_fields.test_jsonfield.TestSaveLoad.test_bulk_update_custom_get_prep_value", diff --git a/django_mongodb_backend/functions.py b/django_mongodb_backend/functions.py index 464dddd6f..42838d1a7 100644 --- a/django_mongodb_backend/functions.py +++ b/django_mongodb_backend/functions.py @@ -1,5 +1,6 @@ from django.db import NotSupportedError from django.db.models.expressions import Func +from django.db.models.functions import JSONArray from django.db.models.functions.comparison import Cast, Coalesce, Greatest, Least, NullIf from django.db.models.functions.datetime import ( Extract, @@ -240,6 +241,7 @@ def register_functions(): Cot.as_mql = cot Extract.as_mql = extract Func.as_mql = func + JSONArray.as_mql = process_lhs Left.as_mql = left Length.as_mql = length Log.as_mql = log From 9ce9ef34463b9970fbb23cc3bbe44143bd408fc6 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 17 Dec 2024 20:49:45 -0500 Subject: [PATCH 5/5] Use DatabaseFeatures.rounds_to_even (new in Django 5.2) --- django_mongodb_backend/features.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/django_mongodb_backend/features.py b/django_mongodb_backend/features.py index 82c358803..0df1615b3 100644 --- a/django_mongodb_backend/features.py +++ b/django_mongodb_backend/features.py @@ -12,6 +12,7 @@ class DatabaseFeatures(BaseDatabaseFeatures): greatest_least_ignores_nulls = True has_json_object_function = False has_native_json_field = True + rounds_to_even = True supports_boolean_expr_in_select_clause = True supports_collation_on_charfield = False supports_column_check_constraints = False @@ -56,8 +57,6 @@ class DatabaseFeatures(BaseDatabaseFeatures): # Pattern lookups that use regexMatch don't work on JSONField: # Unsupported conversion from array to string in $convert "model_fields.test_jsonfield.TestQuerying.test_icontains", - # MongoDB gives ROUND(365, -1)=360 instead of 370 like other databases. - "db_functions.math.test_round.RoundTests.test_integer_with_negative_precision", # Truncating in another timezone doesn't work becauase MongoDB converts # the result back to UTC. "db_functions.datetime.test_extract_trunc.DateFunctionWithTimeZoneTests.test_trunc_func_with_timezone",