@@ -36,8 +36,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
3636 supports_temporal_subtraction = True
3737 # MongoDB stores datetimes in UTC.
3838 supports_timezones = False
39- # Not implemented: https://github.com/mongodb/django-mongodb-backend/issues/7
40- supports_transactions = False
4139 supports_unspecified_pk = True
4240 uses_savepoints = False
4341
@@ -50,8 +48,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
5048 "aggregation.tests.AggregateTestCase.test_order_by_aggregate_transform" ,
5149 # 'NulledTransform' object has no attribute 'as_mql'.
5250 "lookup.tests.LookupTests.test_exact_none_transform" ,
53- # "Save with update_fields did not affect any rows."
54- "basic.tests.SelectOnSaveTests.test_select_on_save_lying_update" ,
5551 # BaseExpression.convert_value() crashes with Decimal128.
5652 "aggregation.tests.AggregateTestCase.test_combine_different_types" ,
5753 "annotations.tests.NonAggregateAnnotationTestCase.test_combined_f_expression_annotation_with_aggregation" ,
@@ -96,13 +92,47 @@ class DatabaseFeatures(BaseDatabaseFeatures):
9692 "expressions.tests.ExpressionOperatorTests.test_lefthand_bitwise_xor_right_null" ,
9793 "expressions.tests.ExpressionOperatorTests.test_lefthand_transformed_field_bitwise_or" ,
9894 }
95+ _django_test_expected_failures_no_transactions = {
96+ # "Save with update_fields did not affect any rows." instead of
97+ # "An error occurred in the current transaction. You can't execute
98+ # queries until the end of the 'atomic' block."
99+ "basic.tests.SelectOnSaveTests.test_select_on_save_lying_update" ,
100+ }
101+ _django_test_expected_failures_transactions = {
102+ # When update_or_create() fails with IntegrityError, the transaction
103+ # is no longer usable.
104+ "get_or_create.tests.UpdateOrCreateTests.test_manual_primary_key_test" ,
105+ "get_or_create.tests.UpdateOrCreateTestsWithManualPKs.test_create_with_duplicate_primary_key" ,
106+ # Tests that require savepoints
107+ "admin_views.tests.AdminViewBasicTest.test_disallowed_to_field" ,
108+ "admin_views.tests.AdminViewPermissionsTest.test_add_view" ,
109+ "admin_views.tests.AdminViewPermissionsTest.test_change_view" ,
110+ "admin_views.tests.AdminViewPermissionsTest.test_change_view_save_as_new" ,
111+ "admin_views.tests.AdminViewPermissionsTest.test_delete_view" ,
112+ "auth_tests.test_views.ChangelistTests.test_view_user_password_is_readonly" ,
113+ "fixtures.tests.FixtureLoadingTests.test_loaddata_app_option" ,
114+ "fixtures.tests.FixtureLoadingTests.test_unmatched_identifier_loading" ,
115+ "fixtures_model_package.tests.FixtureTestCase.test_loaddata" ,
116+ "get_or_create.tests.GetOrCreateTests.test_get_or_create_invalid_params" ,
117+ "get_or_create.tests.UpdateOrCreateTests.test_integrity" ,
118+ "many_to_many.tests.ManyToManyTests.test_add" ,
119+ "many_to_one.tests.ManyToOneTests.test_fk_assignment_and_related_object_cache" ,
120+ "model_fields.test_booleanfield.BooleanFieldTests.test_null_default" ,
121+ "model_fields.test_floatfield.TestFloatField.test_float_validates_object" ,
122+ "multiple_database.tests.QueryTestCase.test_generic_key_cross_database_protection" ,
123+ "multiple_database.tests.QueryTestCase.test_m2m_cross_database_protection" ,
124+ }
99125
100126 @cached_property
101127 def django_test_expected_failures (self ):
102128 expected_failures = super ().django_test_expected_failures
103129 expected_failures .update (self ._django_test_expected_failures )
104130 if not self .is_mongodb_6_3 :
105131 expected_failures .update (self ._django_test_expected_failures_bitwise )
132+ if self .supports_transactions :
133+ expected_failures .update (self ._django_test_expected_failures_transactions )
134+ else :
135+ expected_failures .update (self ._django_test_expected_failures_no_transactions )
106136 return expected_failures
107137
108138 django_test_skips = {
@@ -485,16 +515,6 @@ def django_test_expected_failures(self):
485515 "Connection health checks not implemented." : {
486516 "backends.base.test_base.ConnectionHealthChecksTests" ,
487517 },
488- "transaction.atomic() is not supported." : {
489- "backends.base.test_base.DatabaseWrapperLoggingTests" ,
490- "migrations.test_executor.ExecutorTests.test_atomic_operation_in_non_atomic_migration" ,
491- "migrations.test_operations.OperationTests.test_run_python_atomic" ,
492- },
493- "transaction.rollback() is not supported." : {
494- "transactions.tests.AtomicMiscTests.test_mark_for_rollback_on_error_in_autocommit" ,
495- "transactions.tests.AtomicMiscTests.test_mark_for_rollback_on_error_in_transaction" ,
496- "transactions.tests.NonAutocommitTests.test_orm_query_after_error_and_rollback" ,
497- },
498518 "migrate --fake-initial is not supported." : {
499519 "migrations.test_commands.MigrateTests.test_migrate_fake_initial" ,
500520 "migrations.test_commands.MigrateTests.test_migrate_fake_split_initial" ,
@@ -587,3 +607,20 @@ def supports_atlas_search(self):
587607 return False
588608 else :
589609 return True
610+
611+ @cached_property
612+ def supports_select_union (self ):
613+ # Stage not supported inside of a multi-document transaction: $unionWith
614+ return not self .supports_transactions
615+
616+ @cached_property
617+ def supports_transactions (self ):
618+ """
619+ Transactions are enabled if MongoDB is configured as a replica set or a
620+ sharded cluster.
621+ """
622+ self .connection .ensure_connection ()
623+ client = self .connection .connection .admin
624+ hello = client .command ("hello" )
625+ # a replica set or a sharded cluster
626+ return "setName" in hello or hello .get ("msg" ) == "isdbgrid"
0 commit comments