Skip to content

Commit c822ad6

Browse files
john-partonsarahboyce
authored andcommitted
[5.0.x] Fixed #35628 -- Allowed compatible GeneratedFields for ModelAdmin.date_hierarchy.
Backport of 7f8d839 from main.
1 parent 3aa9acd commit c822ad6

File tree

3 files changed

+58
-3
lines changed

3 files changed

+58
-3
lines changed

django/contrib/admin/checks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1187,7 +1187,7 @@ def _check_date_hierarchy(self, obj):
11871187
)
11881188
]
11891189
else:
1190-
if not isinstance(field, (models.DateField, models.DateTimeField)):
1190+
if field.get_internal_type() not in {"DateField", "DateTimeField"}:
11911191
return must_be(
11921192
"a DateField or DateTimeField",
11931193
option="date_hierarchy",

docs/releases/5.0.8.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,7 @@ Bugfixes
2424
* Fixed a regression in Django 5.0.7 that caused a crash in
2525
``LocaleMiddleware`` when processing a language code over 500 characters
2626
(:ticket:`35627`).
27+
28+
* Fixed a bug in Django 5.0 that caused a system check crash when
29+
``ModelAdmin.date_hierarchy`` was a ``GeneratedField`` with an
30+
``output_field`` of ``DateField`` or ``DateTimeField`` (:ticket:`35628`).

tests/modeladmin/test_checks.py

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44
from django.contrib.admin.options import VERTICAL, ModelAdmin, TabularInline
55
from django.contrib.admin.sites import AdminSite
66
from django.core.checks import Error
7+
from django.db import models
78
from django.db.models import CASCADE, F, Field, ForeignKey, ManyToManyField, Model
89
from django.db.models.functions import Upper
910
from django.forms.models import BaseModelFormSet
10-
from django.test import SimpleTestCase
11+
from django.test import TestCase, skipUnlessDBFeature
1112
from django.test.utils import isolate_apps
1213

1314
from .models import Band, Song, User, ValidationTestInlineModel, ValidationTestModel
1415

1516

16-
class CheckTestCase(SimpleTestCase):
17+
class CheckTestCase(TestCase):
1718
def assertIsInvalid(
1819
self,
1920
model_admin,
@@ -97,6 +98,29 @@ class TestModelAdmin(ModelAdmin):
9798

9899
self.assertIsValid(TestModelAdmin, ValidationTestModel)
99100

101+
@isolate_apps("modeladmin")
102+
def assertGeneratedDateTimeFieldIsValid(self, *, db_persist):
103+
class TestModel(Model):
104+
date = models.DateTimeField()
105+
date_copy = models.GeneratedField(
106+
expression=F("date"),
107+
output_field=models.DateTimeField(),
108+
db_persist=db_persist,
109+
)
110+
111+
class TestModelAdmin(ModelAdmin):
112+
date_hierarchy = "date_copy"
113+
114+
self.assertIsValid(TestModelAdmin, TestModel)
115+
116+
@skipUnlessDBFeature("supports_stored_generated_columns")
117+
def test_valid_case_stored_generated_field(self):
118+
self.assertGeneratedDateTimeFieldIsValid(db_persist=True)
119+
120+
@skipUnlessDBFeature("supports_virtual_generated_columns")
121+
def test_valid_case_virtual_generated_field(self):
122+
self.assertGeneratedDateTimeFieldIsValid(db_persist=False)
123+
100124
def test_field_attname(self):
101125
class TestModelAdmin(ModelAdmin):
102126
raw_id_fields = ["band_id"]
@@ -1016,6 +1040,33 @@ class TestModelAdmin(ModelAdmin):
10161040
"admin.E128",
10171041
)
10181042

1043+
@isolate_apps("modeladmin")
1044+
def assertGeneratedIntegerFieldIsInvalid(self, *, db_persist):
1045+
class TestModel(Model):
1046+
generated = models.GeneratedField(
1047+
expression=models.Value(1),
1048+
output_field=models.IntegerField(),
1049+
db_persist=db_persist,
1050+
)
1051+
1052+
class TestModelAdmin(ModelAdmin):
1053+
date_hierarchy = "generated"
1054+
1055+
self.assertIsInvalid(
1056+
TestModelAdmin,
1057+
TestModel,
1058+
"The value of 'date_hierarchy' must be a DateField or DateTimeField.",
1059+
"admin.E128",
1060+
)
1061+
1062+
@skipUnlessDBFeature("supports_stored_generated_columns")
1063+
def test_related_invalid_field_type_stored_generated_field(self):
1064+
self.assertGeneratedIntegerFieldIsInvalid(db_persist=True)
1065+
1066+
@skipUnlessDBFeature("supports_virtual_generated_columns")
1067+
def test_related_invalid_field_type_virtual_generated_field(self):
1068+
self.assertGeneratedIntegerFieldIsInvalid(db_persist=False)
1069+
10191070
def test_valid_case(self):
10201071
class TestModelAdmin(ModelAdmin):
10211072
date_hierarchy = "pub_date"

0 commit comments

Comments
 (0)