[1.6.x] Fixed #16433 -- Fixed a help_text/read only field interaction that caused an admin crash.
Thanks chris at cogdon.org for the report and admackin for the patch.
Backport of af953c45cc
from master
This commit is contained in:
parent
58157be5ad
commit
ef1259342b
|
@ -320,10 +320,15 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
|
||||||
|
|
||||||
|
|
||||||
def help_text_for_field(name, model):
|
def help_text_for_field(name, model):
|
||||||
try:
|
|
||||||
help_text = model._meta.get_field_by_name(name)[0].help_text
|
|
||||||
except models.FieldDoesNotExist:
|
|
||||||
help_text = ""
|
help_text = ""
|
||||||
|
try:
|
||||||
|
field_data = model._meta.get_field_by_name(name)
|
||||||
|
except models.FieldDoesNotExist:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
field = field_data[0]
|
||||||
|
if not isinstance(field, RelatedObject):
|
||||||
|
help_text = field.help_text
|
||||||
return smart_text(help_text)
|
return smart_text(help_text)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -450,6 +450,10 @@ class GadgetAdmin(admin.ModelAdmin):
|
||||||
return CustomChangeList
|
return CustomChangeList
|
||||||
|
|
||||||
|
|
||||||
|
class ToppingAdmin(admin.ModelAdmin):
|
||||||
|
readonly_fields = ('pizzas',)
|
||||||
|
|
||||||
|
|
||||||
class PizzaAdmin(admin.ModelAdmin):
|
class PizzaAdmin(admin.ModelAdmin):
|
||||||
readonly_fields = ('toppings',)
|
readonly_fields = ('toppings',)
|
||||||
|
|
||||||
|
@ -755,7 +759,7 @@ site.register(Book, inlines=[ChapterInline])
|
||||||
site.register(Promo)
|
site.register(Promo)
|
||||||
site.register(ChapterXtra1, ChapterXtra1Admin)
|
site.register(ChapterXtra1, ChapterXtra1Admin)
|
||||||
site.register(Pizza, PizzaAdmin)
|
site.register(Pizza, PizzaAdmin)
|
||||||
site.register(Topping)
|
site.register(Topping, ToppingAdmin)
|
||||||
site.register(Album, AlbumAdmin)
|
site.register(Album, AlbumAdmin)
|
||||||
site.register(Question)
|
site.register(Question)
|
||||||
site.register(Answer)
|
site.register(Answer)
|
||||||
|
|
|
@ -495,7 +495,7 @@ class Topping(models.Model):
|
||||||
|
|
||||||
class Pizza(models.Model):
|
class Pizza(models.Model):
|
||||||
name = models.CharField(max_length=20)
|
name = models.CharField(max_length=20)
|
||||||
toppings = models.ManyToManyField('Topping')
|
toppings = models.ManyToManyField('Topping', related_name='pizzas')
|
||||||
|
|
||||||
|
|
||||||
class Album(models.Model):
|
class Album(models.Model):
|
||||||
|
|
|
@ -49,7 +49,7 @@ from .models import (Article, BarAccount, CustomArticle, EmptyModel, FooAccount,
|
||||||
OtherStory, ComplexSortedPerson, PluggableSearchPerson, Parent, Child, AdminOrderedField,
|
OtherStory, ComplexSortedPerson, PluggableSearchPerson, Parent, Child, AdminOrderedField,
|
||||||
AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable,
|
AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedCallable,
|
||||||
Report, MainPrepopulated, RelatedPrepopulated, UnorderedObject,
|
Report, MainPrepopulated, RelatedPrepopulated, UnorderedObject,
|
||||||
Simple, UndeletableObject, Choice, ShortMessage, Telegram)
|
Simple, UndeletableObject, Choice, ShortMessage, Telegram, Pizza, Topping)
|
||||||
from .admin import site, site2
|
from .admin import site, site2
|
||||||
|
|
||||||
|
|
||||||
|
@ -3559,6 +3559,17 @@ class ReadonlyTest(TestCase):
|
||||||
self.assertContains(response, '<p>No opinion</p>', html=True)
|
self.assertContains(response, '<p>No opinion</p>', html=True)
|
||||||
self.assertNotContains(response, '<p>(None)</p>')
|
self.assertNotContains(response, '<p>(None)</p>')
|
||||||
|
|
||||||
|
def test_readonly_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
|
||||||
|
"""
|
||||||
|
topping = Topping.objects.create(name='Salami')
|
||||||
|
pizza = Pizza.objects.create(name='Americano')
|
||||||
|
pizza.toppings.add(topping)
|
||||||
|
response = self.client.get('/test_admin/admin/admin_views/topping/add/')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||||
class RawIdFieldsTest(TestCase):
|
class RawIdFieldsTest(TestCase):
|
||||||
|
|
Loading…
Reference in New Issue