Refs #24920 -- Made DecimalField system checks database dependent.

Thanks Tim Graham for the suggestion.
This commit is contained in:
Mariusz Felisiak
2025-12-28 19:21:49 +01:00
committed by GitHub
parent 4afe463950
commit 1c34b8716a
2 changed files with 63 additions and 52 deletions

View File

@@ -1715,10 +1715,11 @@ class DecimalField(Field):
def check(self, **kwargs):
errors = super().check(**kwargs)
databases = kwargs.get("databases") or []
digits_errors = [
*self._check_decimal_places(),
*self._check_max_digits(),
*self._check_decimal_places(databases),
*self._check_max_digits(databases),
]
if not digits_errors:
errors.extend(self._check_decimal_places_and_max_digits(**kwargs))
@@ -1726,29 +1727,34 @@ class DecimalField(Field):
errors.extend(digits_errors)
return errors
def _check_decimal_places(self):
def _check_decimal_places(self, databases):
if self.decimal_places is None:
if (
not connection.features.supports_no_precision_decimalfield
and "supports_no_precision_decimalfield"
not in self.model._meta.required_db_features
):
return [
checks.Error(
"DecimalFields must define a 'decimal_places' attribute.",
obj=self,
id="fields.E130",
)
]
elif self.max_digits is not None:
return [
checks.Error(
"DecimalFields max_digits and decimal_places must both "
"be defined or both omitted.",
obj=self,
id="fields.E135",
),
]
for db in databases:
if not router.allow_migrate_model(db, self.model):
continue
connection = connections[db]
if (
not connection.features.supports_no_precision_decimalfield
and "supports_no_precision_decimalfield"
not in self.model._meta.required_db_features
):
return [
checks.Error(
"DecimalFields must define a 'decimal_places' attribute.",
obj=self,
id="fields.E130",
)
]
elif self.max_digits is not None:
return [
checks.Error(
"DecimalFields max_digits and decimal_places must both "
"be defined or both omitted.",
obj=self,
id="fields.E135",
),
]
else:
try:
decimal_places = int(self.decimal_places)
@@ -1764,29 +1770,34 @@ class DecimalField(Field):
]
return []
def _check_max_digits(self):
def _check_max_digits(self, databases):
if self.max_digits is None:
if (
not connection.features.supports_no_precision_decimalfield
and "supports_no_precision_decimalfield"
not in self.model._meta.required_db_features
):
return [
checks.Error(
"DecimalFields must define a 'max_digits' attribute.",
obj=self,
id="fields.E132",
)
]
elif self.decimal_places is not None:
return [
checks.Error(
"DecimalFields max_digits and decimal_places must both "
"be defined or both omitted.",
obj=self,
id="fields.E135",
),
]
for db in databases:
if not router.allow_migrate_model(db, self.model):
continue
connection = connections[db]
if (
not connection.features.supports_no_precision_decimalfield
and "supports_no_precision_decimalfield"
not in self.model._meta.required_db_features
):
return [
checks.Error(
"DecimalFields must define a 'max_digits' attribute.",
obj=self,
id="fields.E132",
)
]
elif self.decimal_places is not None:
return [
checks.Error(
"DecimalFields max_digits and decimal_places must both "
"be defined or both omitted.",
obj=self,
id="fields.E135",
),
]
else:
try:
max_digits = int(self.max_digits)

View File

@@ -620,7 +620,7 @@ class DecimalFieldTests(TestCase):
id="fields.E132",
),
]
self.assertEqual(field.check(), expected)
self.assertEqual(field.check(databases=self.databases), expected)
def test_both_attributes_omitted_required_db_features(self):
class Model(models.Model):
@@ -639,7 +639,7 @@ class DecimalFieldTests(TestCase):
field = Model._meta.get_field("field")
self.assertEqual(
field.check(),
field.check(databases=self.databases),
[
Error(
"DecimalFields max_digits and decimal_places must both "
@@ -657,7 +657,7 @@ class DecimalFieldTests(TestCase):
field = Model._meta.get_field("field")
self.assertEqual(
field.check(),
field.check(databases=self.databases),
[
Error(
"DecimalFields max_digits and decimal_places must both "
@@ -674,7 +674,7 @@ class DecimalFieldTests(TestCase):
field = Model._meta.get_field("field")
self.assertEqual(
field.check(),
field.check(databases=self.databases),
[
Error(
"'decimal_places' must be a non-negative integer.",
@@ -695,7 +695,7 @@ class DecimalFieldTests(TestCase):
field = Model._meta.get_field("field")
self.assertEqual(
field.check(),
field.check(databases=self.databases),
[
Error(
"'decimal_places' must be a non-negative integer.",
@@ -731,7 +731,7 @@ class DecimalFieldTests(TestCase):
field = models.DecimalField(max_digits=10, decimal_places=10)
field = Model._meta.get_field("field")
self.assertEqual(field.check(), [])
self.assertEqual(field.check(databases=self.databases), [])
@isolate_apps("invalid_models_tests")