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.
This commit is contained in:
parent
cf8d6e9108
commit
af953c45cc
|
@ -327,10 +327,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',)
|
||||||
|
|
||||||
|
@ -763,7 +767,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):
|
||||||
|
|
|
@ -50,7 +50,8 @@ 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, UnchangeableObject, Choice, ShortMessage, Telegram)
|
Simple, UndeletableObject, UnchangeableObject, Choice, ShortMessage,
|
||||||
|
Telegram, Pizza, Topping)
|
||||||
from .admin import site, site2
|
from .admin import site, site2
|
||||||
|
|
||||||
|
|
||||||
|
@ -3638,6 +3639,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