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 = {}
|
prepopulated_fields = {}
|
||||||
formfield_overrides = {}
|
formfield_overrides = {}
|
||||||
readonly_fields = ()
|
readonly_fields = ()
|
||||||
|
ordering = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
|
overrides = FORMFIELD_FOR_DBFIELD_DEFAULTS.copy()
|
||||||
|
@ -189,6 +190,18 @@ class BaseModelAdmin(object):
|
||||||
def get_readonly_fields(self, request, obj=None):
|
def get_readonly_fields(self, request, obj=None):
|
||||||
return self.readonly_fields
|
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):
|
class ModelAdmin(BaseModelAdmin):
|
||||||
"Encapsulates all admin options and functionality for a given model."
|
"Encapsulates all admin options and functionality for a given model."
|
||||||
|
|
||||||
|
@ -202,7 +215,6 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
date_hierarchy = None
|
date_hierarchy = None
|
||||||
save_as = False
|
save_as = False
|
||||||
save_on_top = False
|
save_on_top = False
|
||||||
ordering = None
|
|
||||||
inlines = []
|
inlines = []
|
||||||
|
|
||||||
# Custom templates (designed to be over-ridden in subclasses)
|
# Custom templates (designed to be over-ridden in subclasses)
|
||||||
|
@ -325,18 +337,6 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
'delete': self.has_delete_permission(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):
|
def get_fieldsets(self, request, obj=None):
|
||||||
"Hook for specifying fieldsets for the add form."
|
"Hook for specifying fieldsets for the add form."
|
||||||
if self.declared_fieldsets:
|
if self.declared_fieldsets:
|
||||||
|
@ -1257,9 +1257,6 @@ class InlineModelAdmin(BaseModelAdmin):
|
||||||
fields = form.base_fields.keys() + list(self.get_readonly_fields(request, obj))
|
fields = form.base_fields.keys() + list(self.get_readonly_fields(request, obj))
|
||||||
return [(None, {'fields': fields})]
|
return [(None, {'fields': fields})]
|
||||||
|
|
||||||
def queryset(self, request):
|
|
||||||
return self.model._default_manager.all()
|
|
||||||
|
|
||||||
class StackedInline(InlineModelAdmin):
|
class StackedInline(InlineModelAdmin):
|
||||||
template = 'admin/edit_inline/stacked.html'
|
template = 'admin/edit_inline/stacked.html'
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ subclass::
|
||||||
.. versionadded:: 1.2
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
``fields`` can contain values defined in
|
``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``
|
* ``classes``
|
||||||
A list containing extra CSS classes to apply to the fieldset.
|
A list containing extra CSS classes to apply to the fieldset.
|
||||||
|
@ -504,8 +504,8 @@ subclass::
|
||||||
|
|
||||||
.. attribute:: ModelAdmin.ordering
|
.. attribute:: ModelAdmin.ordering
|
||||||
|
|
||||||
Set ``ordering`` to specify how objects on the admin change list page
|
Set ``ordering`` to specify how lists of objects should be ordered in the
|
||||||
should be ordered. This should be a list or tuple in the same format as a
|
Django admin views. This should be a list or tuple in the same format as a
|
||||||
model's ``ordering`` parameter.
|
model's ``ordering`` parameter.
|
||||||
|
|
||||||
If this isn't provided, the Django admin will use the model's default
|
If this isn't provided, the Django admin will use the model's default
|
||||||
|
@ -1089,8 +1089,36 @@ information.
|
||||||
``InlineModelAdmin`` options
|
``InlineModelAdmin`` options
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
The ``InlineModelAdmin`` class is a subclass of ``ModelAdmin`` so it inherits
|
``InlineModelAdmin`` shares many of the same features as ``ModelAdmin``, and
|
||||||
all the same functionality as well as some of its own:
|
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
|
.. attribute:: InlineModelAdmin.model
|
||||||
|
|
||||||
|
@ -1118,7 +1146,6 @@ all the same functionality as well as some of its own:
|
||||||
|
|
||||||
.. attribute:: InlineModelAdmin.extra
|
.. attribute:: InlineModelAdmin.extra
|
||||||
|
|
||||||
|
|
||||||
This controls the number of extra forms the formset will display in
|
This controls the number of extra forms the formset will display in
|
||||||
addition to the initial forms. See the
|
addition to the initial forms. See the
|
||||||
:doc:`formsets documentation </topics/forms/formsets>` for more
|
:doc:`formsets documentation </topics/forms/formsets>` for more
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
class Band(models.Model):
|
class Band(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
|
@ -8,3 +9,18 @@ class Band(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ('name',)
|
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.test import TestCase
|
||||||
from django.contrib.admin.options import ModelAdmin
|
from django.contrib.admin.options import ModelAdmin
|
||||||
|
|
||||||
from models import Band
|
from models import Band, Song, SongInlineDefaultOrdering, SongInlineNewOrdering
|
||||||
|
|
||||||
class TestAdminOrdering(TestCase):
|
class TestAdminOrdering(TestCase):
|
||||||
"""
|
"""
|
||||||
|
@ -37,3 +37,37 @@ class TestAdminOrdering(TestCase):
|
||||||
ma = BandAdmin(Band, None)
|
ma = BandAdmin(Band, None)
|
||||||
names = [b.name for b in ma.queryset(None)]
|
names = [b.name for b in ma.queryset(None)]
|
||||||
self.assertEqual([u'Radiohead', u'Van Halen', u'Aerosmith'], names)
|
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