diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 27d5657078..4c7ecce82f 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -2840,10 +2840,13 @@ class AutoFieldMixin: pass def get_db_prep_value(self, value, connection, prepared=False): - if not prepared: - value = self.get_prep_value(value) - value = connection.ops.validate_autopk_value(value) - return value + return value if prepared else self.get_prep_value(value) + + def get_db_prep_save(self, value, connection): + if hasattr(value, "as_sql"): + return value + value = connection.ops.validate_autopk_value(value) + return self.get_db_prep_value(value, connection=connection, prepared=False) def contribute_to_class(self, cls, name, **kwargs): if cls._meta.auto_field: diff --git a/tests/backends/tests.py b/tests/backends/tests.py index 3e708401c5..d53cfa5136 100644 --- a/tests/backends/tests.py +++ b/tests/backends/tests.py @@ -19,6 +19,7 @@ from django.db import ( from django.db.backends.base.base import BaseDatabaseWrapper from django.db.backends.signals import connection_created from django.db.backends.utils import CursorWrapper +from django.db.models import BigAutoField, Value from django.db.models.sql.constants import CURSOR from django.test import ( TestCase, @@ -966,7 +967,7 @@ class ThreadTests(TransactionTestCase): connection.dec_thread_sharing() -class MySQLPKZeroTests(TestCase): +class MySQLAutoPKZeroTests(TestCase): """ Zero as id for AutoField should raise exception in MySQL, because MySQL does not allow zero for autoincrement primary key if the @@ -975,8 +976,15 @@ class MySQLPKZeroTests(TestCase): @skipIfDBFeature("allows_auto_pk_0") def test_zero_as_autoval(self): - with self.assertRaises(ValueError): + msg = "The database backend does not accept 0 as a value for AutoField." + with self.assertRaisesMessage(ValueError, msg): Square.objects.create(id=0, root=0, square=1) + with self.assertRaisesMessage(ValueError, msg): + Square.objects.create(id=Value(0, BigAutoField()), root=0, square=1) + + @skipIfDBFeature("allows_auto_pk_0") + def test_no_error_when_filtering_with_expression(self): + self.assertSequenceEqual(Square.objects.filter(id=Value(0, BigAutoField())), ()) class DBConstraintTestCase(TestCase): diff --git a/tests/model_fields/test_integerfield.py b/tests/model_fields/test_integerfield.py index 34966304fb..e5c9156afe 100644 --- a/tests/model_fields/test_integerfield.py +++ b/tests/model_fields/test_integerfield.py @@ -198,7 +198,7 @@ class IntegerFieldTests(TestCase): (TypeError, {}), (TypeError, set()), (TypeError, object()), - (TypeError, complex()), + (TypeError, complex(0, 1)), (ValueError, "non-numeric string"), (ValueError, b"non-numeric byte-string"), ]