mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #26060 -- Fixed crash with reverse OneToOneField in ModelAdmin.readonly_fields.
This commit is contained in:
committed by
Tim Graham
parent
fb4272f0e6
commit
9a33d3d764
@@ -67,6 +67,43 @@ ERROR_MESSAGE = "Please enter the correct username and password \
|
||||
for a staff account. Note that both fields may be case-sensitive."
|
||||
|
||||
|
||||
class AdminFieldExtractionMixin(object):
|
||||
"""
|
||||
Helper methods for extracting data from AdminForm.
|
||||
"""
|
||||
def get_admin_form_fields(self, response):
|
||||
"""
|
||||
Return a list of AdminFields for the AdminForm in the response.
|
||||
"""
|
||||
admin_form = response.context['adminform']
|
||||
fieldsets = list(admin_form)
|
||||
|
||||
field_lines = []
|
||||
for fieldset in fieldsets:
|
||||
field_lines += list(fieldset)
|
||||
|
||||
fields = []
|
||||
for field_line in field_lines:
|
||||
fields += list(field_line)
|
||||
|
||||
return fields
|
||||
|
||||
def get_admin_readonly_fields(self, response):
|
||||
"""
|
||||
Return the readonly fields for the response's AdminForm.
|
||||
"""
|
||||
return [f for f in self.get_admin_form_fields(response) if f.is_readonly]
|
||||
|
||||
def get_admin_readonly_field(self, response, field_name):
|
||||
"""
|
||||
Return the readonly field for the given field_name.
|
||||
"""
|
||||
admin_readonly_fields = self.get_admin_readonly_fields(response)
|
||||
for field in admin_readonly_fields:
|
||||
if field.field['name'] == field_name:
|
||||
return field
|
||||
|
||||
|
||||
@override_settings(PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'],
|
||||
ROOT_URLCONF="admin_views.urls",
|
||||
USE_I18N=True, USE_L10N=False, LANGUAGE_CODE='en')
|
||||
@@ -4556,7 +4593,7 @@ class SeleniumAdminViewsIETests(SeleniumAdminViewsFirefoxTests):
|
||||
|
||||
@override_settings(PASSWORD_HASHERS=['django.contrib.auth.hashers.SHA1PasswordHasher'],
|
||||
ROOT_URLCONF="admin_views.urls")
|
||||
class ReadonlyTest(TestCase):
|
||||
class ReadonlyTest(AdminFieldExtractionMixin, TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
@@ -4677,7 +4714,7 @@ class ReadonlyTest(TestCase):
|
||||
self.assertContains(response, '<p>No opinion</p>', html=True)
|
||||
self.assertNotContains(response, '<p>(None)</p>')
|
||||
|
||||
def test_readonly_backwards_ref(self):
|
||||
def test_readonly_manytomany_backwards_ref(self):
|
||||
"""
|
||||
Regression test for #16433 - backwards references for related objects
|
||||
broke if the related field is read-only due to the help_text attribute
|
||||
@@ -4688,6 +4725,26 @@ class ReadonlyTest(TestCase):
|
||||
response = self.client.get(reverse('admin:admin_views_topping_add'))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_readonly_onetoone_backwards_ref(self):
|
||||
"""
|
||||
Can reference a reverse OneToOneField in ModelAdmin.readonly_fields.
|
||||
"""
|
||||
v1 = Villain.objects.create(name='Adam')
|
||||
pl = Plot.objects.create(name='Test Plot', team_leader=v1, contact=v1)
|
||||
pd = PlotDetails.objects.create(details='Brand New Plot', plot=pl)
|
||||
|
||||
response = self.client.get(reverse('admin:admin_views_plotproxy_change', args=(pl.pk,)))
|
||||
field = self.get_admin_readonly_field(response, 'plotdetails')
|
||||
self.assertEqual(field.contents(), 'Brand New Plot')
|
||||
|
||||
# The reverse relation also works if the OneToOneField is null.
|
||||
pd.plot = None
|
||||
pd.save()
|
||||
|
||||
response = self.client.get(reverse('admin:admin_views_plotproxy_change', args=(pl.pk,)))
|
||||
field = self.get_admin_readonly_field(response, 'plotdetails')
|
||||
self.assertEqual(field.contents(), '-') # default empty value
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango20Warning) # for allow_tags deprecation
|
||||
def test_readonly_field_overrides(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user