Introduced ModelAdmin.get_fields() and refactored get_fieldsets() to use it.
Refs #18681. This also starts the deprecation of ModelAdmin.declared_fieldsets
This commit is contained in:
parent
61ecb5f48a
commit
ebb3e50243
|
@ -2,6 +2,7 @@ from collections import OrderedDict
|
||||||
import copy
|
import copy
|
||||||
import operator
|
import operator
|
||||||
from functools import partial, reduce, update_wrapper
|
from functools import partial, reduce, update_wrapper
|
||||||
|
import warnings
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -238,13 +239,49 @@ class BaseModelAdmin(six.with_metaclass(RenameBaseModelAdminMethods)):
|
||||||
|
|
||||||
return db_field.formfield(**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:
|
if self.fieldsets:
|
||||||
return self.fieldsets
|
return self.fieldsets
|
||||||
elif self.fields:
|
elif self.fields:
|
||||||
return [(None, {'fields': self.fields})]
|
return [(None, {'fields': self.fields})]
|
||||||
return None
|
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):
|
def get_ordering(self, request):
|
||||||
"""
|
"""
|
||||||
|
@ -478,13 +515,11 @@ class ModelAdmin(BaseModelAdmin):
|
||||||
'delete': self.has_delete_permission(request),
|
'delete': self.has_delete_permission(request),
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_fieldsets(self, request, obj=None):
|
def get_fields(self, request, obj=None):
|
||||||
"Hook for specifying fieldsets for the add form."
|
if self.fields:
|
||||||
if self.declared_fieldsets:
|
return self.fields
|
||||||
return self.declared_fieldsets
|
|
||||||
form = self.get_form(request, obj, fields=None)
|
form = self.get_form(request, obj, fields=None)
|
||||||
fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
|
return list(form.base_fields) + list(self.get_readonly_fields(request, obj))
|
||||||
return [(None, {'fields': fields})]
|
|
||||||
|
|
||||||
def get_form(self, request, obj=None, **kwargs):
|
def get_form(self, request, obj=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -1657,12 +1692,11 @@ class InlineModelAdmin(BaseModelAdmin):
|
||||||
|
|
||||||
return inlineformset_factory(self.parent_model, self.model, **defaults)
|
return inlineformset_factory(self.parent_model, self.model, **defaults)
|
||||||
|
|
||||||
def get_fieldsets(self, request, obj=None):
|
def get_fields(self, request, obj=None):
|
||||||
if self.declared_fieldsets:
|
if self.fields:
|
||||||
return self.declared_fieldsets
|
return self.fields
|
||||||
form = self.get_formset(request, obj, fields=None).form
|
form = self.get_formset(request, obj, fields=None).form
|
||||||
fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
|
return list(form.base_fields) + list(self.get_readonly_fields(request, obj))
|
||||||
return [(None, {'fields': fields})]
|
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
queryset = super(InlineModelAdmin, self).get_queryset(request)
|
queryset = super(InlineModelAdmin, self).get_queryset(request)
|
||||||
|
|
|
@ -426,6 +426,8 @@ these changes.
|
||||||
* ``django.utils.datastructures.SortedDict`` will be removed. Use
|
* ``django.utils.datastructures.SortedDict`` will be removed. Use
|
||||||
:class:`collections.OrderedDict` from the Python standard library instead.
|
:class:`collections.OrderedDict` from the Python standard library instead.
|
||||||
|
|
||||||
|
* ``ModelAdmin.declared_fieldsets`` will be removed.
|
||||||
|
|
||||||
2.0
|
2.0
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1218,6 +1218,14 @@ templates used by the :class:`ModelAdmin` views:
|
||||||
changelist that will be linked to the change view, as described in the
|
changelist that will be linked to the change view, as described in the
|
||||||
:attr:`ModelAdmin.list_display_links` section.
|
: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)
|
.. method:: ModelAdmin.get_fieldsets(self, request, obj=None)
|
||||||
|
|
||||||
The ``get_fieldsets`` method is given the ``HttpRequest`` and the ``obj``
|
The ``get_fieldsets`` method is given the ``HttpRequest`` and the ``obj``
|
||||||
|
|
|
@ -113,6 +113,11 @@ Minor features
|
||||||
* The admin's search fields can now be customized per-request thanks to the new
|
* The admin's search fields can now be customized per-request thanks to the new
|
||||||
:meth:`django.contrib.admin.ModelAdmin.get_search_fields` method.
|
: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
|
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
|
<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
|
will search ``myapp/sql/`` as documented. The old location will continue to
|
||||||
work until Django 1.9.
|
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.
|
||||||
|
|
|
@ -51,6 +51,12 @@ class ModelAdminTests(TestCase):
|
||||||
self.assertEqual(list(ma.get_form(request).base_fields),
|
self.assertEqual(list(ma.get_form(request).base_fields),
|
||||||
['name', 'bio', 'sign_date'])
|
['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):
|
def test_default_fieldsets(self):
|
||||||
# fieldsets_add and fieldsets_change should return a special data structure that
|
# 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
|
# 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)
|
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),
|
self.assertEqual(ma.get_fieldsets(request),
|
||||||
[(None, {'fields': ['name']})])
|
[(None, {'fields': ['name']})])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue