Commit b3520da9 authored by Jannis Leidel's avatar Jannis Leidel
Browse files

Fixed #13862 -- Added an ordering option to InlineModelAdmin and cleaned up...

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
parent 1e7bb904
Loading
Loading
Loading
Loading
+13 −16
Original line number Diff line number Diff line
@@ -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'

+33 −6
Original line number Diff line number Diff line
@@ -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
+16 −0
Original line number Diff line number Diff line
# 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', )
+35 −1
Original line number Diff line number Diff line
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)
 No newline at end of file