Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Introduced ModelAdmin.get_fields() and refactored get_fieldsets() to …

…use it.

Refs #18681.

This also starts the deprecation of ModelAdmin.declared_fieldsets
  • Loading branch information...
commit ebb3e50243448545c7314a1932a9067ddca5960b 1 parent 61ecb5f
@loic loic authored timgraham committed
View
60 django/contrib/admin/options.py
@@ -2,6 +2,7 @@
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 @@ def formfield_for_manytomany(self, db_field, request=None, **kwargs):
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 @@ def get_model_perms(self, request):
'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 @@ def is_valid(self):
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)
View
2  docs/internals/deprecation.txt
@@ -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
---
View
8 docs/ref/contrib/admin/index.txt
@@ -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``
View
13 docs/releases/1.7.txt
@@ -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.
View
10 tests/modeladmin/tests.py
@@ -51,6 +51,12 @@ def test_default_fields(self):
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 BandAdmin(ModelAdmin):
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']})])
Please sign in to comment.
Something went wrong with that request. Please try again.