Commit ebb3e502 authored by Loic Bistuer's avatar Loic Bistuer Committed by Tim Graham
Browse files

Introduced ModelAdmin.get_fields() and refactored get_fieldsets() to use it.

Refs #18681.

This also starts the deprecation of ModelAdmin.declared_fieldsets
parent 61ecb5f4
Loading
Loading
Loading
Loading
+47 −13
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ from collections import OrderedDict
import copy
import operator
from functools import partial, reduce, update_wrapper
import warnings

from django import forms
from django.conf import settings
@@ -238,13 +239,49 @@ class BaseModelAdmin(six.with_metaclass(RenameBaseModelAdminMethods)):

        return db_field.formfield(**kwargs)

    def _declared_fieldsets(self):
    @property
    def declared_fieldsets(self):
        warnings.warn(
            "ModelAdmin.declared_fieldsets is deprecated and "
            "will be removed in Django 1.9.",
            PendingDeprecationWarning, stacklevel=2
        )

        if self.fieldsets:
            return self.fieldsets
        elif self.fields:
            return [(None, {'fields': self.fields})]
        return None
    declared_fieldsets = property(_declared_fieldsets)

    def get_fields(self, request, obj=None):
        """
        Hook for specifying fields.
        """
        return self.fields

    def get_fieldsets(self, request, obj=None):
        """
        Hook for specifying fieldsets.
        """
        # We access the property and check if it triggers a warning.
        # If it does, then it's ours and we can safely ignore it, but if
        # it doesn't then it has been overriden so we must warn about the
        # deprecation.
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            declared_fieldsets = self.declared_fieldsets
        if len(w) != 1 or not issubclass(w[0].category, PendingDeprecationWarning):
            warnings.warn(
                "ModelAdmin.declared_fieldsets is deprecated and "
                "will be removed in Django 1.9.",
                PendingDeprecationWarning
            )
            if declared_fieldsets:
                return declared_fieldsets

        if self.fieldsets:
            return self.fieldsets
        return [(None, {'fields': self.get_fields(request, obj)})]

    def get_ordering(self, request):
        """
@@ -478,13 +515,11 @@ class ModelAdmin(BaseModelAdmin):
            'delete': self.has_delete_permission(request),
        }

    def get_fieldsets(self, request, obj=None):
        "Hook for specifying fieldsets for the add form."
        if self.declared_fieldsets:
            return self.declared_fieldsets
    def get_fields(self, request, obj=None):
        if self.fields:
            return self.fields
        form = self.get_form(request, obj, fields=None)
        fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
        return [(None, {'fields': fields})]
        return list(form.base_fields) + list(self.get_readonly_fields(request, obj))

    def get_form(self, request, obj=None, **kwargs):
        """
@@ -1657,12 +1692,11 @@ class InlineModelAdmin(BaseModelAdmin):

        return inlineformset_factory(self.parent_model, self.model, **defaults)

    def get_fieldsets(self, request, obj=None):
        if self.declared_fieldsets:
            return self.declared_fieldsets
    def get_fields(self, request, obj=None):
        if self.fields:
            return self.fields
        form = self.get_formset(request, obj, fields=None).form
        fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
        return [(None, {'fields': fields})]
        return list(form.base_fields) + list(self.get_readonly_fields(request, obj))

    def get_queryset(self, request):
        queryset = super(InlineModelAdmin, self).get_queryset(request)
+2 −0
Original line number Diff line number Diff line
@@ -426,6 +426,8 @@ these changes.
* ``django.utils.datastructures.SortedDict`` will be removed. Use
  :class:`collections.OrderedDict` from the Python standard library instead.

* ``ModelAdmin.declared_fieldsets`` will be removed.

2.0
---

+8 −0
Original line number Diff line number Diff line
@@ -1218,6 +1218,14 @@ templates used by the :class:`ModelAdmin` views:
    changelist that will be linked to the change view, as described in the
    :attr:`ModelAdmin.list_display_links` section.

.. method:: ModelAdmin.get_fields(self, request, obj=None)

    .. versionadded:: 1.7

    The ``get_fields`` method is given the ``HttpRequest`` and the ``obj``
    being edited (or ``None`` on an add form) and is expected to return a list
    of fields, as described above in the :attr:`ModelAdmin.fields` section.

.. method:: ModelAdmin.get_fieldsets(self, request, obj=None)

    The ``get_fieldsets`` method is given the ``HttpRequest`` and the ``obj``
+13 −0
Original line number Diff line number Diff line
@@ -113,6 +113,11 @@ Minor features
* The admin's search fields can now be customized per-request thanks to the new
  :meth:`django.contrib.admin.ModelAdmin.get_search_fields` method.

* The :meth:`ModelAdmin.get_fields()
  <django.contrib.admin.ModelAdmin.get_fields>` method may be overridden to
  customize the value of :attr:`ModelAdmin.fields
  <django.contrib.admin.ModelAdmin.fields>`.

Backwards incompatible changes in 1.7
=====================================

@@ -182,3 +187,11 @@ than simply ``myapp/models.py``, Django would look for :ref:`initial SQL data
<initial-sql>` in ``myapp/models/sql/``. This bug has been fixed so that Django
will search ``myapp/sql/`` as documented. The old location will continue to
work until Django 1.9.

``declared_fieldsets`` attribute on ``ModelAdmin.``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

``ModelAdmin.declared_fieldsets`` was deprecated. Despite being a private API,
it will go through a regular deprecation path. This attribute was mostly used
by methods that bypassed ``ModelAdmin.get_fieldsets()`` but this was considered
a bug and has been addressed.
+10 −0
Original line number Diff line number Diff line
@@ -51,6 +51,12 @@ class ModelAdminTests(TestCase):
        self.assertEqual(list(ma.get_form(request).base_fields),
            ['name', 'bio', 'sign_date'])

        self.assertEqual(list(ma.get_fields(request)),
            ['name', 'bio', 'sign_date'])

        self.assertEqual(list(ma.get_fields(request, self.band)),
            ['name', 'bio', 'sign_date'])

    def test_default_fieldsets(self):
        # fieldsets_add and fieldsets_change should return a special data structure that
        # is used in the templates. They should generate the "right thing" whether we
@@ -97,6 +103,10 @@ class ModelAdminTests(TestCase):

        ma = BandAdmin(Band, self.site)

        self.assertEqual(list(ma.get_fields(request)), ['name'])

        self.assertEqual(list(ma.get_fields(request, self.band)), ['name'])

        self.assertEqual(ma.get_fieldsets(request),
            [(None, {'fields': ['name']})])