diff options
| author | John Parton <john.parton.iv@gmail.com> | 2024-07-24 13:53:06 -0500 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2024-08-05 15:28:40 +0200 |
| commit | 88ebcb1856deef5ab777601a735c9954ac723325 (patch) | |
| tree | d3ee3c3eb9e337ec9961363bd39b92e980bf831a | |
| parent | 06fb6434b3b5750c678292bbf52944508c40566c (diff) | |
[5.1.x] Fixed #35628 -- Allowed compatible GeneratedFields for ModelAdmin.date_hierarchy.
Backport of 7f8d839722b72aeb3ec5a4278ae57c18283acacd from main.
| -rw-r--r-- | django/contrib/admin/checks.py | 2 | ||||
| -rw-r--r-- | docs/releases/5.0.8.txt | 4 | ||||
| -rw-r--r-- | tests/modeladmin/test_checks.py | 55 |
3 files changed, 58 insertions, 3 deletions
diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py index 94e700cf68..a4d7066d10 100644 --- a/django/contrib/admin/checks.py +++ b/django/contrib/admin/checks.py @@ -1184,7 +1184,7 @@ class ModelAdminChecks(BaseModelAdminChecks): ) ] else: - if not isinstance(field, (models.DateField, models.DateTimeField)): + if field.get_internal_type() not in {"DateField", "DateTimeField"}: return must_be( "a DateField or DateTimeField", option="date_hierarchy", diff --git a/docs/releases/5.0.8.txt b/docs/releases/5.0.8.txt index df3bc9ae2a..31de9985c4 100644 --- a/docs/releases/5.0.8.txt +++ b/docs/releases/5.0.8.txt @@ -24,3 +24,7 @@ Bugfixes * Fixed a regression in Django 5.0.7 that caused a crash in ``LocaleMiddleware`` when processing a language code over 500 characters (:ticket:`35627`). + +* Fixed a bug in Django 5.0 that caused a system check crash when + ``ModelAdmin.date_hierarchy`` was a ``GeneratedField`` with an + ``output_field`` of ``DateField`` or ``DateTimeField`` (:ticket:`35628`). diff --git a/tests/modeladmin/test_checks.py b/tests/modeladmin/test_checks.py index f767a6c92b..94a80ca006 100644 --- a/tests/modeladmin/test_checks.py +++ b/tests/modeladmin/test_checks.py @@ -4,16 +4,17 @@ from django.contrib.admin import BooleanFieldListFilter, SimpleListFilter from django.contrib.admin.options import VERTICAL, ModelAdmin, TabularInline from django.contrib.admin.sites import AdminSite from django.core.checks import Error +from django.db import models from django.db.models import CASCADE, F, Field, ForeignKey, ManyToManyField, Model from django.db.models.functions import Upper from django.forms.models import BaseModelFormSet -from django.test import SimpleTestCase +from django.test import TestCase, skipUnlessDBFeature from django.test.utils import isolate_apps from .models import Band, Song, User, ValidationTestInlineModel, ValidationTestModel -class CheckTestCase(SimpleTestCase): +class CheckTestCase(TestCase): def assertIsInvalid( self, model_admin, @@ -97,6 +98,29 @@ class RawIdCheckTests(CheckTestCase): self.assertIsValid(TestModelAdmin, ValidationTestModel) + @isolate_apps("modeladmin") + def assertGeneratedDateTimeFieldIsValid(self, *, db_persist): + class TestModel(Model): + date = models.DateTimeField() + date_copy = models.GeneratedField( + expression=F("date"), + output_field=models.DateTimeField(), + db_persist=db_persist, + ) + + class TestModelAdmin(ModelAdmin): + date_hierarchy = "date_copy" + + self.assertIsValid(TestModelAdmin, TestModel) + + @skipUnlessDBFeature("supports_stored_generated_columns") + def test_valid_case_stored_generated_field(self): + self.assertGeneratedDateTimeFieldIsValid(db_persist=True) + + @skipUnlessDBFeature("supports_virtual_generated_columns") + def test_valid_case_virtual_generated_field(self): + self.assertGeneratedDateTimeFieldIsValid(db_persist=False) + def test_field_attname(self): class TestModelAdmin(ModelAdmin): raw_id_fields = ["band_id"] @@ -1029,6 +1053,33 @@ class DateHierarchyCheckTests(CheckTestCase): "admin.E128", ) + @isolate_apps("modeladmin") + def assertGeneratedIntegerFieldIsInvalid(self, *, db_persist): + class TestModel(Model): + generated = models.GeneratedField( + expression=models.Value(1), + output_field=models.IntegerField(), + db_persist=db_persist, + ) + + class TestModelAdmin(ModelAdmin): + date_hierarchy = "generated" + + self.assertIsInvalid( + TestModelAdmin, + TestModel, + "The value of 'date_hierarchy' must be a DateField or DateTimeField.", + "admin.E128", + ) + + @skipUnlessDBFeature("supports_stored_generated_columns") + def test_related_invalid_field_type_stored_generated_field(self): + self.assertGeneratedIntegerFieldIsInvalid(db_persist=True) + + @skipUnlessDBFeature("supports_virtual_generated_columns") + def test_related_invalid_field_type_virtual_generated_field(self): + self.assertGeneratedIntegerFieldIsInvalid(db_persist=False) + def test_valid_case(self): class TestModelAdmin(ModelAdmin): date_hierarchy = "pub_date" |
