Loading AUTHORS +2 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ answer newbie questions, and generally made Django that much better: Matt Dennenbaum deric@monowerks.com Max Derkachev <mderk@yandex.ru> Carlos Matías de la Torre <cmdelatorre@gmail.com> Rajesh Dhawan <rajesh.dhawan@gmail.com> Sander Dijkhuis <sander.dijkhuis@gmail.com> Jordan Dimov <s3x3y1@gmail.com> Loading Loading @@ -205,6 +206,7 @@ answer newbie questions, and generally made Django that much better: Stefane Fermgier <sf@fermigier.com> J. Pablo Fernandez <pupeno@pupeno.com> Maciej Fijalkowski Juan Pedro Fisanotti <fisadev@gmail.com> Ben Firshman <ben@firshman.co.uk> Matthew Flanagan <http://wadofstuff.blogspot.com> Eric Floehr <eric@intellovations.com> Loading django/contrib/admin/options.py +21 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,19 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): ) return db_field.formfield(**kwargs) def get_field_queryset(self, db, db_field, request): """ If the ModelAdmin specifies ordering, the queryset should respect that ordering. Otherwise don't specify the queryset, let the field decide (returns None in that case). """ related_admin = self.admin_site._registry.get(db_field.rel.to, None) if related_admin is not None: ordering = related_admin.get_ordering(request) if ordering is not None and ordering != (): return db_field.rel.to._default_manager.using(db).order_by(*ordering).complex_filter(db_field.rel.limit_choices_to) return None def formfield_for_foreignkey(self, db_field, request=None, **kwargs): """ Get a form Field for a ForeignKey. Loading @@ -171,6 +184,10 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): }) kwargs['empty_label'] = db_field.blank and _('None') or None queryset = self.get_field_queryset(db, db_field, request) if queryset is not None: kwargs['queryset'] = queryset return db_field.formfield(**kwargs) def formfield_for_manytomany(self, db_field, request=None, **kwargs): Loading @@ -190,6 +207,10 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)): kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) queryset = self.get_field_queryset(db, db_field, request) if queryset is not None: kwargs['queryset'] = queryset return db_field.formfield(**kwargs) def _declared_fieldsets(self): Loading tests/admin_ordering/models.py +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ class Song(models.Model): band = models.ForeignKey(Band) name = models.CharField(max_length=100) duration = models.IntegerField() other_interpreters = models.ManyToManyField(Band, related_name='covers') class Meta: ordering = ('name',) Loading tests/admin_ordering/tests.py +48 −0 Original line number Diff line number Diff line from __future__ import absolute_import, unicode_literals from django.test import TestCase, RequestFactory from django.contrib import admin from django.contrib.admin.options import ModelAdmin from django.contrib.auth.models import User Loading Loading @@ -104,3 +105,50 @@ class TestInlineModelAdminOrdering(TestCase): inline = SongInlineNewOrdering(self.b, None) names = [s.name for s in inline.queryset(request)] self.assertEqual(['Jaded', 'Pink', 'Dude (Looks Like a Lady)'], names) class TestRelatedFieldsAdminOrdering(TestCase): def setUp(self): self.b1 = Band(name='Pink Floyd', bio='', rank=1) self.b1.save() self.b2 = Band(name='Foo Fighters', bio='', rank=5) self.b2.save() # we need to register a custom ModelAdmin (instead of just using # ModelAdmin) because the field creator tries to find the ModelAdmin # for the related model class SongAdmin(admin.ModelAdmin): pass admin.site.register(Song, SongAdmin) def check_ordering_of_field_choices(self, correct_ordering): fk_field = admin.site._registry[Song].formfield_for_foreignkey(Song.band.field) m2m_field = admin.site._registry[Song].formfield_for_manytomany(Song.other_interpreters.field) self.assertEqual(list(fk_field.queryset), correct_ordering) self.assertEqual(list(m2m_field.queryset), correct_ordering) def test_no_admin_fallback_to_model_ordering(self): # should be ordered by name (as defined by the model) self.check_ordering_of_field_choices([self.b2, self.b1]) def test_admin_with_no_ordering_fallback_to_model_ordering(self): class NoOrderingBandAdmin(admin.ModelAdmin): pass admin.site.register(Band, NoOrderingBandAdmin) # should be ordered by name (as defined by the model) self.check_ordering_of_field_choices([self.b2, self.b1]) def test_admin_ordering_beats_model_ordering(self): class StaticOrderingBandAdmin(admin.ModelAdmin): ordering = ('rank', ) admin.site.register(Band, StaticOrderingBandAdmin) # should be ordered by rank (defined by the ModelAdmin) self.check_ordering_of_field_choices([self.b1, self.b2]) def tearDown(self): admin.site.unregister(Song) if Band in admin.site._registry: admin.site.unregister(Band) Loading
AUTHORS +2 −0 Original line number Diff line number Diff line Loading @@ -165,6 +165,7 @@ answer newbie questions, and generally made Django that much better: Matt Dennenbaum deric@monowerks.com Max Derkachev <mderk@yandex.ru> Carlos Matías de la Torre <cmdelatorre@gmail.com> Rajesh Dhawan <rajesh.dhawan@gmail.com> Sander Dijkhuis <sander.dijkhuis@gmail.com> Jordan Dimov <s3x3y1@gmail.com> Loading Loading @@ -205,6 +206,7 @@ answer newbie questions, and generally made Django that much better: Stefane Fermgier <sf@fermigier.com> J. Pablo Fernandez <pupeno@pupeno.com> Maciej Fijalkowski Juan Pedro Fisanotti <fisadev@gmail.com> Ben Firshman <ben@firshman.co.uk> Matthew Flanagan <http://wadofstuff.blogspot.com> Eric Floehr <eric@intellovations.com> Loading
django/contrib/admin/options.py +21 −0 Original line number Diff line number Diff line Loading @@ -157,6 +157,19 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): ) return db_field.formfield(**kwargs) def get_field_queryset(self, db, db_field, request): """ If the ModelAdmin specifies ordering, the queryset should respect that ordering. Otherwise don't specify the queryset, let the field decide (returns None in that case). """ related_admin = self.admin_site._registry.get(db_field.rel.to, None) if related_admin is not None: ordering = related_admin.get_ordering(request) if ordering is not None and ordering != (): return db_field.rel.to._default_manager.using(db).order_by(*ordering).complex_filter(db_field.rel.limit_choices_to) return None def formfield_for_foreignkey(self, db_field, request=None, **kwargs): """ Get a form Field for a ForeignKey. Loading @@ -171,6 +184,10 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): }) kwargs['empty_label'] = db_field.blank and _('None') or None queryset = self.get_field_queryset(db, db_field, request) if queryset is not None: kwargs['queryset'] = queryset return db_field.formfield(**kwargs) def formfield_for_manytomany(self, db_field, request=None, **kwargs): Loading @@ -190,6 +207,10 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)): elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)): kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) queryset = self.get_field_queryset(db, db_field, request) if queryset is not None: kwargs['queryset'] = queryset return db_field.formfield(**kwargs) def _declared_fieldsets(self): Loading
tests/admin_ordering/models.py +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ class Song(models.Model): band = models.ForeignKey(Band) name = models.CharField(max_length=100) duration = models.IntegerField() other_interpreters = models.ManyToManyField(Band, related_name='covers') class Meta: ordering = ('name',) Loading
tests/admin_ordering/tests.py +48 −0 Original line number Diff line number Diff line from __future__ import absolute_import, unicode_literals from django.test import TestCase, RequestFactory from django.contrib import admin from django.contrib.admin.options import ModelAdmin from django.contrib.auth.models import User Loading Loading @@ -104,3 +105,50 @@ class TestInlineModelAdminOrdering(TestCase): inline = SongInlineNewOrdering(self.b, None) names = [s.name for s in inline.queryset(request)] self.assertEqual(['Jaded', 'Pink', 'Dude (Looks Like a Lady)'], names) class TestRelatedFieldsAdminOrdering(TestCase): def setUp(self): self.b1 = Band(name='Pink Floyd', bio='', rank=1) self.b1.save() self.b2 = Band(name='Foo Fighters', bio='', rank=5) self.b2.save() # we need to register a custom ModelAdmin (instead of just using # ModelAdmin) because the field creator tries to find the ModelAdmin # for the related model class SongAdmin(admin.ModelAdmin): pass admin.site.register(Song, SongAdmin) def check_ordering_of_field_choices(self, correct_ordering): fk_field = admin.site._registry[Song].formfield_for_foreignkey(Song.band.field) m2m_field = admin.site._registry[Song].formfield_for_manytomany(Song.other_interpreters.field) self.assertEqual(list(fk_field.queryset), correct_ordering) self.assertEqual(list(m2m_field.queryset), correct_ordering) def test_no_admin_fallback_to_model_ordering(self): # should be ordered by name (as defined by the model) self.check_ordering_of_field_choices([self.b2, self.b1]) def test_admin_with_no_ordering_fallback_to_model_ordering(self): class NoOrderingBandAdmin(admin.ModelAdmin): pass admin.site.register(Band, NoOrderingBandAdmin) # should be ordered by name (as defined by the model) self.check_ordering_of_field_choices([self.b2, self.b1]) def test_admin_ordering_beats_model_ordering(self): class StaticOrderingBandAdmin(admin.ModelAdmin): ordering = ('rank', ) admin.site.register(Band, StaticOrderingBandAdmin) # should be ordered by rank (defined by the ModelAdmin) self.check_ordering_of_field_choices([self.b1, self.b2]) def tearDown(self): admin.site.unregister(Song) if Band in admin.site._registry: admin.site.unregister(Band)