Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #13862 -- Added an ordering option to InlineModelAdmin and clea…

…ned up documentation for it a bit. Thanks, Simon Meers, rasca and cogat.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@14882 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit b3520da9ac113ed435cb6aa135b0559780d9c530 1 parent 1e7bb90
@jezdez jezdez authored
View
29 django/contrib/admin/options.py
@@ -67,6 +67,7 @@ class BaseModelAdmin(object):
prepopulated_fields = {}
formfield_overrides = {}
readonly_fields = ()
+ ordering = None
def __init__(self):
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
@@ -189,6 +190,18 @@ def _declared_fieldsets(self):
def get_readonly_fields(self, request, obj=None):
return self.readonly_fields
+ def queryset(self, request):
+ """
+ Returns a QuerySet of all model instances that can be edited by the
+ admin site. This is used by changelist_view.
+ """
+ qs = self.model._default_manager.get_query_set()
+ # TODO: this should be handled by some parameter to the ChangeList.
+ ordering = self.ordering or () # otherwise we might try to *None, which is bad ;)
+ if ordering:
+ qs = qs.order_by(*ordering)
+ return qs
+
class ModelAdmin(BaseModelAdmin):
"Encapsulates all admin options and functionality for a given model."
@@ -202,7 +215,6 @@ class ModelAdmin(BaseModelAdmin):
date_hierarchy = None
save_as = False
save_on_top = False
- ordering = None
inlines = []
# Custom templates (designed to be over-ridden in subclasses)
@@ -325,18 +337,6 @@ def get_model_perms(self, request):
'delete': self.has_delete_permission(request),
}
- def queryset(self, request):
- """
- Returns a QuerySet of all model instances that can be edited by the
- admin site. This is used by changelist_view.
- """
- qs = self.model._default_manager.get_query_set()
- # TODO: this should be handled by some parameter to the ChangeList.
- ordering = self.ordering or () # otherwise we might try to *None, which is bad ;)
- if ordering:
- qs = qs.order_by(*ordering)
- return qs
-
def get_fieldsets(self, request, obj=None):
"Hook for specifying fieldsets for the add form."
if self.declared_fieldsets:
@@ -1257,9 +1257,6 @@ def get_fieldsets(self, request, obj=None):
fields = form.base_fields.keys() + list(self.get_readonly_fields(request, obj))
return [(None, {'fields': fields})]
- def queryset(self, request):
- return self.model._default_manager.all()
-
class StackedInline(InlineModelAdmin):
template = 'admin/edit_inline/stacked.html'
View
39 docs/ref/contrib/admin/index.txt
@@ -180,7 +180,7 @@ subclass::
.. versionadded:: 1.2
``fields`` can contain values defined in
- :attr:`ModelAdmin.readonly_fields` to be displayed as read-only.
+ :attr:`~ModelAdmin.readonly_fields` to be displayed as read-only.
* ``classes``
A list containing extra CSS classes to apply to the fieldset.
@@ -504,8 +504,8 @@ subclass::
.. attribute:: ModelAdmin.ordering
- Set ``ordering`` to specify how objects on the admin change list page
- should be ordered. This should be a list or tuple in the same format as a
+ Set ``ordering`` to specify how lists of objects should be ordered in the
+ Django admin views. This should be a list or tuple in the same format as a
model's ``ordering`` parameter.
If this isn't provided, the Django admin will use the model's default
@@ -1089,8 +1089,36 @@ information.
``InlineModelAdmin`` options
-----------------------------
-The ``InlineModelAdmin`` class is a subclass of ``ModelAdmin`` so it inherits
-all the same functionality as well as some of its own:
+``InlineModelAdmin`` shares many of the same features as ``ModelAdmin``, and
+adds some of its own (the shared features are actually defined in the
+``BaseModelAdmin`` superclass). The shared features are:
+
+- :attr:`~InlineModelAdmin.form`
+- :attr:`~ModelAdmin.fieldsets`
+- :attr:`~ModelAdmin.fields`
+- :attr:`~ModelAdmin.exclude`
+- :attr:`~ModelAdmin.filter_horizontal`
+- :attr:`~ModelAdmin.filter_vertical`
+- :attr:`~ModelAdmin.prepopulated_fields`
+- :attr:`~ModelAdmin.radio_fields`
+- :attr:`~InlineModelAdmin.raw_id_fields`
+
+.. versionadded:: 1.1
+
+- :meth:`~ModelAdmin.formfield_for_foreignkey`
+- :meth:`~ModelAdmin.formfield_for_manytomany`
+
+.. versionadded:: 1.2
+
+- :attr:`~ModelAdmin.readonly_fields`
+- :attr:`~ModelAdmin.formfield_overrides`
+
+.. versionadded:: 1.3
+
+- :attr:`~ModelAdmin.ordering`
+- :meth:`~ModelAdmin.queryset`
+
+The ``InlineModelAdmin`` class adds:
.. attribute:: InlineModelAdmin.model
@@ -1118,7 +1146,6 @@ all the same functionality as well as some of its own:
.. attribute:: InlineModelAdmin.extra
-
This controls the number of extra forms the formset will display in
addition to the initial forms. See the
:doc:`formsets documentation </topics/forms/formsets>` for more
View
16 tests/regressiontests/admin_ordering/models.py
@@ -1,5 +1,6 @@
# coding: utf-8
from django.db import models
+from django.contrib import admin
class Band(models.Model):
name = models.CharField(max_length=100)
@@ -8,3 +9,18 @@ class Band(models.Model):
class Meta:
ordering = ('name',)
+
+class Song(models.Model):
+ band = models.ForeignKey(Band)
+ name = models.CharField(max_length=100)
+ duration = models.IntegerField()
+
+ class Meta:
+ ordering = ('name',)
+
+class SongInlineDefaultOrdering(admin.StackedInline):
+ model = Song
+
+class SongInlineNewOrdering(admin.StackedInline):
+ model = Song
+ ordering = ('duration', )
View
36 tests/regressiontests/admin_ordering/tests.py
@@ -1,7 +1,7 @@
from django.test import TestCase
from django.contrib.admin.options import ModelAdmin
-from models import Band
+from models import Band, Song, SongInlineDefaultOrdering, SongInlineNewOrdering
class TestAdminOrdering(TestCase):
"""
@@ -37,3 +37,37 @@ class BandAdmin(ModelAdmin):
ma = BandAdmin(Band, None)
names = [b.name for b in ma.queryset(None)]
self.assertEqual([u'Radiohead', u'Van Halen', u'Aerosmith'], names)
+
+class TestInlineModelAdminOrdering(TestCase):
+ """
+ Let's make sure that InlineModelAdmin.queryset uses the ordering we define
+ in InlineModelAdmin.
+ """
+
+ def setUp(self):
+ b = Band(name='Aerosmith', bio='', rank=3)
+ b.save()
+ self.b = b
+ s1 = Song(band=b, name='Pink', duration=235)
+ s1.save()
+ s2 = Song(band=b, name='Dude (Looks Like a Lady)', duration=264)
+ s2.save()
+ s3 = Song(band=b, name='Jaded', duration=214)
+ s3.save()
+
+ def test_default_ordering(self):
+ """
+ The default ordering should be by name, as specified in the inner Meta
+ class.
+ """
+ inline = SongInlineDefaultOrdering(self.b, None)
+ names = [s.name for s in inline.queryset(None)]
+ self.assertEqual([u'Dude (Looks Like a Lady)', u'Jaded', u'Pink'], names)
+
+ def test_specified_ordering(self):
+ """
+ Let's check with ordering set to something different than the default.
+ """
+ inline = SongInlineNewOrdering(self.b, None)
+ names = [s.name for s in inline.queryset(None)]
+ self.assertEqual([u'Jaded', u'Pink', u'Dude (Looks Like a Lady)'], names)
Please sign in to comment.
Something went wrong with that request. Please try again.