[4.0.x] Fixed #33547 -- Fixed error when rendering invalid inlines with readonly fields in admin.
Regression inde95c82667
. Thanks David Glenck for the report. Backport of445b075def
from main
This commit is contained in:
parent
be4a106930
commit
82f25266bf
|
@ -138,7 +138,11 @@ def cell_count(inline_admin_form):
|
||||||
# Count all visible fields.
|
# Count all visible fields.
|
||||||
for line in fieldset:
|
for line in fieldset:
|
||||||
for field in line:
|
for field in line:
|
||||||
if not field.field.is_hidden:
|
try:
|
||||||
|
is_hidden = field.field.is_hidden
|
||||||
|
except AttributeError:
|
||||||
|
is_hidden = field.field["is_hidden"]
|
||||||
|
if not is_hidden:
|
||||||
count += 1
|
count += 1
|
||||||
if inline_admin_form.formset.can_delete:
|
if inline_admin_form.formset.can_delete:
|
||||||
# Delete checkbox
|
# Delete checkbox
|
||||||
|
|
|
@ -15,3 +15,7 @@ Bugfixes
|
||||||
* Prevented, following a regression in Django 4.0.1, :djadmin:`makemigrations`
|
* Prevented, following a regression in Django 4.0.1, :djadmin:`makemigrations`
|
||||||
from generating infinite migrations for a model with ``ManyToManyField`` to
|
from generating infinite migrations for a model with ``ManyToManyField`` to
|
||||||
a lowercased swappable model such as ``'auth.user'`` (:ticket:`33515`).
|
a lowercased swappable model such as ``'auth.user'`` (:ticket:`33515`).
|
||||||
|
|
||||||
|
* Fixed a regression in Django 4.0 that caused a crash when rendering invalid
|
||||||
|
inlines with :attr:`~django.contrib.admin.ModelAdmin.readonly_fields` in the
|
||||||
|
admin (:ticket:`33547`).
|
||||||
|
|
|
@ -5,6 +5,7 @@ import random
|
||||||
|
|
||||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
@ -204,6 +205,9 @@ class Question(models.Model):
|
||||||
text = models.CharField(max_length=40)
|
text = models.CharField(max_length=40)
|
||||||
poll = models.ForeignKey(Poll, models.CASCADE)
|
poll = models.ForeignKey(Poll, models.CASCADE)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
raise ValidationError("Always invalid model.")
|
||||||
|
|
||||||
|
|
||||||
class Novel(models.Model):
|
class Novel(models.Model):
|
||||||
name = models.CharField(max_length=40)
|
name = models.CharField(max_length=40)
|
||||||
|
|
|
@ -241,6 +241,22 @@ class TestInline(TestDataMixin, TestCase):
|
||||||
# column cells
|
# column cells
|
||||||
self.assertContains(response, "<p>Callable in QuestionInline</p>")
|
self.assertContains(response, "<p>Callable in QuestionInline</p>")
|
||||||
|
|
||||||
|
def test_model_error_inline_with_readonly_field(self):
|
||||||
|
poll = Poll.objects.create(name="Test poll")
|
||||||
|
data = {
|
||||||
|
"question_set-TOTAL_FORMS": 1,
|
||||||
|
"question_set-INITIAL_FORMS": 0,
|
||||||
|
"question_set-MAX_NUM_FORMS": 0,
|
||||||
|
"_save": "Save",
|
||||||
|
"question_set-0-text": "Question",
|
||||||
|
"question_set-0-poll": poll.pk,
|
||||||
|
}
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("admin:admin_inlines_poll_change", args=(poll.pk,)),
|
||||||
|
data,
|
||||||
|
)
|
||||||
|
self.assertContains(response, "Always invalid model.")
|
||||||
|
|
||||||
def test_help_text(self):
|
def test_help_text(self):
|
||||||
"""
|
"""
|
||||||
The inlines' model field help texts are displayed when using both the
|
The inlines' model field help texts are displayed when using both the
|
||||||
|
|
Loading…
Reference in New Issue