Forráskód Böngészése

Fixed #35127 -- Made Model.full_clean() ignore GeneratedFields.

Thanks Claude Paroz for the report.

Regression in f333e3513e8bdf5ffeb6eeb63021c230082e6f95.
Mariusz Felisiak 1 éve
szülő
commit
4879907223

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

@@ -1628,7 +1628,7 @@ class Model(AltersData, metaclass=ModelBase):
 
         errors = {}
         for f in self._meta.fields:
-            if f.name in exclude:
+            if f.name in exclude or f.generated:
                 continue
             # Skip validation for empty fields with blank=True. The developer
             # is responsible for making sure they have a valid value.

+ 3 - 0
docs/releases/5.0.2.txt

@@ -15,3 +15,6 @@ Bugfixes
 
 * Fixed a regression in Django 5.0 where links in the admin had an incorrect
   color (:ticket:`35121`).
+
+* Fixed a bug in Django 5.0 that caused a crash of ``Model.full_clean()`` on
+  models with a ``GeneratedField`` (:ticket:`35127`).

+ 2 - 2
tests/model_fields/models.py

@@ -502,7 +502,7 @@ class GeneratedModel(models.Model):
         output_field=models.IntegerField(),
         db_persist=True,
     )
-    fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True)
+    fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True, blank=True)
 
     class Meta:
         required_db_features = {"supports_stored_generated_columns"}
@@ -516,7 +516,7 @@ class GeneratedModelVirtual(models.Model):
         output_field=models.IntegerField(),
         db_persist=False,
     )
-    fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True)
+    fk = models.ForeignKey(Foo, on_delete=models.CASCADE, null=True, blank=True)
 
     class Meta:
         required_db_features = {"supports_virtual_generated_columns"}

+ 8 - 0
tests/model_fields/test_generatedfield.py

@@ -168,6 +168,14 @@ class GeneratedFieldTestMixin:
         with self.assertRaisesMessage(AttributeError, msg):
             m.field
 
+    def test_full_clean(self):
+        m = self.base_model(a=1, b=2)
+        # full_clean() ignores GeneratedFields.
+        m.full_clean()
+        m.save()
+        m = self._refresh_if_needed(m)
+        self.assertEqual(m.field, 3)
+
     def test_create(self):
         m = self.base_model.objects.create(a=1, b=2)
         m = self._refresh_if_needed(m)