Fixed #30231 -- Fixed admin filter horizontal/vertical verbose_name generation.
Co-authored-by: David Smith <smithdc@gmail.com>
This commit is contained in:
parent
06e5f7ae16
commit
45bef6706a
|
@ -218,12 +218,10 @@
|
||||||
// instantiate a new SelectFilter instance for it.
|
// instantiate a new SelectFilter instance for it.
|
||||||
if (typeof SelectFilter !== 'undefined') {
|
if (typeof SelectFilter !== 'undefined') {
|
||||||
$('.selectfilter').each(function(index, value) {
|
$('.selectfilter').each(function(index, value) {
|
||||||
const namearr = value.name.split('-');
|
SelectFilter.init(value.id, this.dataset.fieldName, false);
|
||||||
SelectFilter.init(value.id, namearr[namearr.length - 1], false);
|
|
||||||
});
|
});
|
||||||
$('.selectfilterstacked').each(function(index, value) {
|
$('.selectfilterstacked').each(function(index, value) {
|
||||||
const namearr = value.name.split('-');
|
SelectFilter.init(value.id, this.dataset.fieldName, true);
|
||||||
SelectFilter.init(value.id, namearr[namearr.length - 1], true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -283,12 +281,10 @@
|
||||||
// If any SelectFilter widgets were added, instantiate a new instance.
|
// If any SelectFilter widgets were added, instantiate a new instance.
|
||||||
if (typeof SelectFilter !== "undefined") {
|
if (typeof SelectFilter !== "undefined") {
|
||||||
$(".selectfilter").each(function(index, value) {
|
$(".selectfilter").each(function(index, value) {
|
||||||
const namearr = value.name.split('-');
|
SelectFilter.init(value.id, this.dataset.fieldName, false);
|
||||||
SelectFilter.init(value.id, namearr[namearr.length - 1], false);
|
|
||||||
});
|
});
|
||||||
$(".selectfilterstacked").each(function(index, value) {
|
$(".selectfilterstacked").each(function(index, value) {
|
||||||
const namearr = value.name.split('-');
|
SelectFilter.init(value.id, this.dataset.fieldName, true);
|
||||||
SelectFilter.init(value.id, namearr[namearr.length - 1], true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,9 +5,10 @@ from django.db import models
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Author, BinaryTree, CapoFamiglia, Chapter, Child, ChildModel1, ChildModel2,
|
Author, BinaryTree, CapoFamiglia, Chapter, Child, ChildModel1, ChildModel2,
|
||||||
Consigliere, EditablePKBook, ExtraTerrestrial, Fashionista, FootNote,
|
Class, Consigliere, Course, CourseProxy, CourseProxy1, CourseProxy2,
|
||||||
Holder, Holder2, Holder3, Holder4, Holder5, Inner, Inner2, Inner3,
|
EditablePKBook, ExtraTerrestrial, Fashionista, FootNote, Holder, Holder2,
|
||||||
Inner4Stacked, Inner4Tabular, Inner5Stacked, Inner5Tabular, NonAutoPKBook,
|
Holder3, Holder4, Holder5, Inner, Inner2, Inner3, Inner4Stacked,
|
||||||
|
Inner4Tabular, Inner5Stacked, Inner5Tabular, NonAutoPKBook,
|
||||||
NonAutoPKBookChild, Novel, NovelReadonlyChapter, OutfitItem,
|
NonAutoPKBookChild, Novel, NovelReadonlyChapter, OutfitItem,
|
||||||
ParentModelWithCustomPk, Person, Poll, Profile, ProfileCollection,
|
ParentModelWithCustomPk, Person, Poll, Profile, ProfileCollection,
|
||||||
Question, ReadOnlyInline, ShoppingWeakness, Sighting, SomeChildModel,
|
Question, ReadOnlyInline, ShoppingWeakness, Sighting, SomeChildModel,
|
||||||
|
@ -300,6 +301,47 @@ class FashonistaStackedInline(admin.StackedInline):
|
||||||
model = Fashionista
|
model = Fashionista
|
||||||
|
|
||||||
|
|
||||||
|
# Admin for #30231
|
||||||
|
class ClassStackedHorizontal(admin.StackedInline):
|
||||||
|
model = Class
|
||||||
|
extra = 1
|
||||||
|
filter_horizontal = ['person']
|
||||||
|
|
||||||
|
|
||||||
|
class ClassAdminStackedHorizontal(admin.ModelAdmin):
|
||||||
|
inlines = [ClassStackedHorizontal]
|
||||||
|
|
||||||
|
|
||||||
|
class ClassTabularHorizontal(admin.TabularInline):
|
||||||
|
model = Class
|
||||||
|
extra = 1
|
||||||
|
filter_horizontal = ['person']
|
||||||
|
|
||||||
|
|
||||||
|
class ClassAdminTabularHorizontal(admin.ModelAdmin):
|
||||||
|
inlines = [ClassTabularHorizontal]
|
||||||
|
|
||||||
|
|
||||||
|
class ClassTabularVertical(admin.TabularInline):
|
||||||
|
model = Class
|
||||||
|
extra = 1
|
||||||
|
filter_vertical = ['person']
|
||||||
|
|
||||||
|
|
||||||
|
class ClassAdminTabularVertical(admin.ModelAdmin):
|
||||||
|
inlines = [ClassTabularVertical]
|
||||||
|
|
||||||
|
|
||||||
|
class ClassStackedVertical(admin.StackedInline):
|
||||||
|
model = Class
|
||||||
|
extra = 1
|
||||||
|
filter_vertical = ['person']
|
||||||
|
|
||||||
|
|
||||||
|
class ClassAdminStackedVertical(admin.ModelAdmin):
|
||||||
|
inlines = [ClassStackedVertical]
|
||||||
|
|
||||||
|
|
||||||
site.register(TitleCollection, inlines=[TitleInline])
|
site.register(TitleCollection, inlines=[TitleInline])
|
||||||
# Test bug #12561 and #12778
|
# Test bug #12561 and #12778
|
||||||
# only ModelAdmin media
|
# only ModelAdmin media
|
||||||
|
@ -327,3 +369,7 @@ site.register(Teacher, TeacherAdmin)
|
||||||
site.register(Chapter, inlines=[FootNoteNonEditableInlineCustomForm])
|
site.register(Chapter, inlines=[FootNoteNonEditableInlineCustomForm])
|
||||||
site.register(OutfitItem, inlines=[WeaknessInlineCustomForm])
|
site.register(OutfitItem, inlines=[WeaknessInlineCustomForm])
|
||||||
site.register(Person, inlines=[AuthorTabularInline, FashonistaStackedInline])
|
site.register(Person, inlines=[AuthorTabularInline, FashonistaStackedInline])
|
||||||
|
site.register(Course, ClassAdminStackedHorizontal)
|
||||||
|
site.register(CourseProxy, ClassAdminStackedVertical)
|
||||||
|
site.register(CourseProxy1, ClassAdminTabularVertical)
|
||||||
|
site.register(CourseProxy2, ClassAdminTabularHorizontal)
|
||||||
|
|
|
@ -294,6 +294,38 @@ class SomeChildModel(models.Model):
|
||||||
parent = models.ForeignKey(SomeParentModel, models.CASCADE)
|
parent = models.ForeignKey(SomeParentModel, models.CASCADE)
|
||||||
readonly_field = models.CharField(max_length=1)
|
readonly_field = models.CharField(max_length=1)
|
||||||
|
|
||||||
|
|
||||||
|
# Models for #30231
|
||||||
|
class Course(models.Model):
|
||||||
|
name = models.CharField(max_length=128)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class Class(models.Model):
|
||||||
|
person = models.ManyToManyField(Person, verbose_name='attendant')
|
||||||
|
course = models.ForeignKey(Course, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
|
||||||
|
class CourseProxy(Course):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
|
class CourseProxy1(Course):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
|
class CourseProxy2(Course):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
proxy = True
|
||||||
|
|
||||||
|
|
||||||
# Other models
|
# Other models
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1356,3 +1356,37 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(self.selenium.find_elements_by_css_selector(tabular_inline_formset_selector)), 1
|
len(self.selenium.find_elements_by_css_selector(tabular_inline_formset_selector)), 1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_inlines_verbose_name(self):
|
||||||
|
"""
|
||||||
|
The item added by the "Add another XXX" link must use the correct
|
||||||
|
verbose_name in the inline form.
|
||||||
|
"""
|
||||||
|
self.admin_login(username='super', password='secret')
|
||||||
|
# Each combination of horizontal/vertical fiter with stacked/tabular
|
||||||
|
# inlines.
|
||||||
|
tests = [
|
||||||
|
'admin:admin_inlines_course_add',
|
||||||
|
'admin:admin_inlines_courseproxy_add',
|
||||||
|
'admin:admin_inlines_courseproxy1_add',
|
||||||
|
'admin:admin_inlines_courseproxy2_add',
|
||||||
|
]
|
||||||
|
css_selector = '.dynamic-class_set#class_set-%s h2'
|
||||||
|
|
||||||
|
for url_name in tests:
|
||||||
|
with self.subTest(url=url_name):
|
||||||
|
self.selenium.get(self.live_server_url + reverse(url_name))
|
||||||
|
# First inline shows the verbose_name.
|
||||||
|
available, chosen = self.selenium.find_elements_by_css_selector(css_selector % 0)
|
||||||
|
self.assertEqual(available.text, 'AVAILABLE ATTENDANT')
|
||||||
|
self.assertEqual(chosen.text, 'CHOSEN ATTENDANT')
|
||||||
|
# Added inline should also have the correct verbose_name.
|
||||||
|
self.selenium.find_element_by_link_text('Add another Class').click()
|
||||||
|
available, chosen = self.selenium.find_elements_by_css_selector(css_selector % 1)
|
||||||
|
self.assertEqual(available.text, 'AVAILABLE ATTENDANT')
|
||||||
|
self.assertEqual(chosen.text, 'CHOSEN ATTENDANT')
|
||||||
|
# Third inline should also have the correct verbose_name.
|
||||||
|
self.selenium.find_element_by_link_text('Add another Class').click()
|
||||||
|
available, chosen = self.selenium.find_elements_by_css_selector(css_selector % 2)
|
||||||
|
self.assertEqual(available.text, 'AVAILABLE ATTENDANT')
|
||||||
|
self.assertEqual(chosen.text, 'CHOSEN ATTENDANT')
|
||||||
|
|
Loading…
Reference in New Issue