1
0
mirror of https://github.com/django/django.git synced 2025-03-09 17:02:43 +00:00

[5.0.x] Fixed #35223 -- Made Model.full_clean() ignore fields with db_default when validating empty values.

Thanks Brian Ibbotson for the report.

Regression in 7414704e88d73dafbcfbb85f9bc54cb6111439d3.

Backport of 1570ef02f34037d32218d463342592debccf915c from main.
This commit is contained in:
Ben Cail 2024-03-05 16:36:11 -05:00 committed by Mariusz Felisiak
parent f931cbec21
commit 5f07460a67
3 changed files with 26 additions and 2 deletions

View File

@ -30,7 +30,7 @@ from django.db.models import NOT_PROVIDED, ExpressionWrapper, IntegerField, Max,
from django.db.models.constants import LOOKUP_SEP
from django.db.models.constraints import CheckConstraint, UniqueConstraint
from django.db.models.deletion import CASCADE, Collector
from django.db.models.expressions import RawSQL
from django.db.models.expressions import DatabaseDefault, RawSQL
from django.db.models.fields.related import (
ForeignObjectRel,
OneToOneField,
@ -1568,6 +1568,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:

View File

@ -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`).

View File

@ -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):