2
0
Эх сурвалжийг харах

Fixed #34319 -- Fixed Model.validate_constraints() crash on ValidationError with no code.

Thanks Mateusz Kurowski for the report.

Regression in 667105877e6723c6985399803a364848891513cc.
Mariusz Felisiak 2 жил өмнө
parent
commit
2fd755b361

+ 4 - 1
django/db/models/base.py

@@ -1444,7 +1444,10 @@ class Model(AltersData, metaclass=ModelBase):
                 try:
                     constraint.validate(model_class, self, exclude=exclude, using=using)
                 except ValidationError as e:
-                    if e.code == "unique" and len(constraint.fields) == 1:
+                    if (
+                        getattr(e, "code", None) == "unique"
+                        and len(constraint.fields) == 1
+                    ):
                         errors.setdefault(constraint.fields[0], []).append(e)
                     else:
                         errors = e.update_error_dict(errors)

+ 2 - 1
docs/releases/4.1.7.txt

@@ -12,4 +12,5 @@ in 4.1.6.
 Bugfixes
 ========
 
-* ...
+* Fixed a bug in Django 4.1 that caused a crash of model validation on
+  ``ValidationError`` with no ``code`` (:ticket:`34319`).

+ 21 - 1
tests/constraints/tests.py

@@ -3,7 +3,7 @@ from unittest import mock
 from django.core.exceptions import ValidationError
 from django.db import IntegrityError, connection, models
 from django.db.models import F
-from django.db.models.constraints import BaseConstraint
+from django.db.models.constraints import BaseConstraint, UniqueConstraint
 from django.db.models.functions import Lower
 from django.db.transaction import atomic
 from django.test import SimpleTestCase, TestCase, skipIfDBFeature, skipUnlessDBFeature
@@ -589,6 +589,26 @@ class UniqueConstraintTests(TestCase):
         with self.assertRaisesMessage(ValidationError, msg):
             UniqueConstraintConditionProduct(name=obj2.name).validate_constraints()
 
+    def test_model_validation_constraint_no_code_error(self):
+        class ValidateNoCodeErrorConstraint(UniqueConstraint):
+            def validate(self, model, instance, **kwargs):
+                raise ValidationError({"name": ValidationError("Already exists.")})
+
+        class NoCodeErrorConstraintModel(models.Model):
+            name = models.CharField(max_length=255)
+
+            class Meta:
+                constraints = [
+                    ValidateNoCodeErrorConstraint(
+                        Lower("name"),
+                        name="custom_validate_no_code_error",
+                    )
+                ]
+
+        msg = "{'name': ['Already exists.']}"
+        with self.assertRaisesMessage(ValidationError, msg):
+            NoCodeErrorConstraintModel(name="test").validate_constraints()
+
     def test_validate(self):
         constraint = UniqueConstraintProduct._meta.constraints[0]
         msg = "Unique constraint product with this Name and Color already exists."