Fixed #13862 -- Added an ordering option to InlineModelAdmin and cleaned 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
This commit is contained in:
parent
1e7bb904df
commit
b3520da9ac
|
@ -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 @@ class BaseModelAdmin(object):
|
|||
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 @@ class ModelAdmin(BaseModelAdmin):
|
|||
'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 @@ class InlineModelAdmin(BaseModelAdmin):
|
|||
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'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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', )
|
||||
|
|
|
@ -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 TestAdminOrdering(TestCase):
|
|||
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)
|
Loading…
Reference in New Issue