summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Cail <bcail@crossway.org>2024-03-05 16:36:11 -0500
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2024-03-08 05:55:25 +0100
commit1570ef02f34037d32218d463342592debccf915c (patch)
treee377a44159473f9c10628399b6af3ca5b50da788
parent1669e54965e22d9bfd0cc8f8fb969704ac608163 (diff)
Fixed #35223 -- Made Model.full_clean() ignore fields with db_default when validating empty values.
Thanks Brian Ibbotson for the report. Regression in 7414704e88d73dafbcfbb85f9bc54cb6111439d3.
-rw-r--r--django/db/models/base.py4
-rw-r--r--docs/releases/5.0.4.txt5
-rw-r--r--tests/field_defaults/tests.py18
3 files changed, 26 insertions, 1 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index ce1c7d1046..9c8ab7bfa6 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -29,6 +29,7 @@ from django.db import (
from django.db.models import NOT_PROVIDED, ExpressionWrapper, IntegerField, Max, Value
from django.db.models.constants import LOOKUP_SEP
from django.db.models.deletion import CASCADE, Collector
+from django.db.models.expressions import DatabaseDefault
from django.db.models.fields.related import (
ForeignObjectRel,
OneToOneField,
@@ -1633,6 +1634,9 @@ class Model(AltersData, metaclass=ModelBase):
raw_value = getattr(self, f.attname)
if f.blank and raw_value in f.empty_values:
continue
+ # Skip validation for empty fields when db_default is used.
+ if isinstance(raw_value, DatabaseDefault):
+ continue
try:
setattr(self, f.attname, f.clean(raw_value, self))
except ValidationError as e:
diff --git a/docs/releases/5.0.4.txt b/docs/releases/5.0.4.txt
index 52d3bdfb0e..d15c28d83d 100644
--- a/docs/releases/5.0.4.txt
+++ b/docs/releases/5.0.4.txt
@@ -9,4 +9,7 @@ Django 5.0.4 fixes several bugs in 5.0.3.
Bugfixes
========
-* ...
+* Fixed a bug in Django 5.0 that caused a crash of ``Model.full_clean()`` on
+ fields with expressions in ``db_default``. As a consequence,
+ ``Model.full_clean()`` no longer validates for empty values in fields with
+ ``db_default`` (:ticket:`35223`).
diff --git a/tests/field_defaults/tests.py b/tests/field_defaults/tests.py
index c05d966bdb..6a5c75c36a 100644
--- a/tests/field_defaults/tests.py
+++ b/tests/field_defaults/tests.py
@@ -2,6 +2,7 @@ from datetime import datetime
from decimal import Decimal
from math import pi
+from django.core.exceptions import ValidationError
from django.db import connection
from django.db.models import Case, F, FloatField, Value, When
from django.db.models.expressions import (
@@ -169,6 +170,23 @@ class DefaultTests(TestCase):
years = DBDefaultsFunction.objects.values_list("year", flat=True)
self.assertCountEqual(years, [2000, datetime.now().year])
+ def test_full_clean(self):
+ obj = DBArticle()
+ obj.full_clean()
+ obj.save()
+ obj.refresh_from_db()
+ self.assertEqual(obj.headline, "Default headline")
+
+ obj = DBArticle(headline="Other title")
+ obj.full_clean()
+ obj.save()
+ obj.refresh_from_db()
+ self.assertEqual(obj.headline, "Other title")
+
+ obj = DBArticle(headline="")
+ with self.assertRaises(ValidationError):
+ obj.full_clean()
+
class AllowedDefaultTests(SimpleTestCase):
def test_allowed(self):