docs start for formset/inline support
parent
a07ce7260c
commit
8c42893abd
|
|
@ -57,10 +57,12 @@ use the ``base_form`` and ``base_fieldsets`` instead. The ``PolymorphicChildMode
|
|||
automatically detect the additional fields that the child model has, display those in a separate fieldset.
|
||||
|
||||
|
||||
Polymorphic Inlines
|
||||
-------------------
|
||||
Using polymorphic models in standard inlines
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To add a polymorphic child model as an Inline for another model, add a field to the inline's readonly_fields list formed by the lowercased name of the polymorphic parent model with the string "_ptr" appended to it. Otherwise, trying to save that model in the admin will raise an AttributeError with the message "can't set attribute".
|
||||
To add a polymorphic child model as an Inline for another model, add a field to the inline's ``readonly_fields`` list
|
||||
formed by the lowercased name of the polymorphic parent model with the string ``_ptr`` appended to it.
|
||||
Otherwise, trying to save that model in the admin will raise an AttributeError with the message "can't set attribute".
|
||||
|
||||
|
||||
.. _admin-example:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
Formsets
|
||||
========
|
||||
|
||||
Polymorphic models can be used in formsets.
|
||||
|
||||
Use the :func:`polymorphic.formsets.polymorphic_inlineformset_factory` function to generate the formset.
|
||||
As extra parameter, the factory needs to know how to display the child models.
|
||||
Provide a list of :class:`polymorphic.formsets.PolymorphicFormSetChild` objects for this
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from polymorphic.formsets import polymorphic_child_forms_factory
|
||||
|
|
@ -49,6 +49,7 @@ Getting started
|
|||
|
||||
quickstart
|
||||
admin
|
||||
formsets
|
||||
performance
|
||||
|
||||
Advanced topics
|
||||
|
|
|
|||
|
|
@ -6,8 +6,10 @@ from django.core.urlresolvers import resolve
|
|||
from django.utils import six
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .helpers import PolymorphicInlineSupportMixin
|
||||
|
||||
class PolymorphicChildModelAdmin(admin.ModelAdmin):
|
||||
|
||||
class PolymorphicChildModelAdmin(PolymorphicInlineSupportMixin, admin.ModelAdmin):
|
||||
"""
|
||||
The *optional* base class for the admin interface of derived models.
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ class PolymorphicChildModelFilter(admin.SimpleListFilter):
|
|||
"""
|
||||
An admin list filter for the PolymorphicParentModelAdmin which enables
|
||||
filtering by its child models.
|
||||
|
||||
This can be used in the parent admin:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
list_filter = (PolymorphicChildModelFilter,)
|
||||
"""
|
||||
title = _('Type')
|
||||
parameter_name = 'polymorphic_ctype'
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ This makes sure that admin fieldsets/layout settings are exported to the templat
|
|||
"""
|
||||
from django.contrib.admin.helpers import InlineAdminFormSet, InlineAdminForm
|
||||
|
||||
from ..formsets import BasePolymorphicModelFormSet
|
||||
from polymorphic.formsets import BasePolymorphicModelFormSet
|
||||
|
||||
|
||||
class InlinePolymorphicAdminForm(InlineAdminForm):
|
||||
|
|
@ -75,6 +75,14 @@ class InlinePolymorphicAdminFormSet(InlineAdminFormSet):
|
|||
class PolymorphicInlineSupportMixin(object):
|
||||
"""
|
||||
A Mixin to add to the regular admin, so it can work with our polymorphic inlines.
|
||||
|
||||
This mixin needs to be included in the admin that hosts the ``inlines``.
|
||||
It makes sure the generated admin forms have different fieldsets/fields
|
||||
depending on the polymorphic type of the form instance.
|
||||
|
||||
This is achieved by overwriting :func:`get_inline_formsets` to return
|
||||
an :class:`InlinePolymorphicAdminFormSet` instead of a standard Django
|
||||
:class:`~django.contrib.admin.helpers.InlineAdminFormSet` for the polymorphic formsets.
|
||||
"""
|
||||
|
||||
def get_inline_formsets(self, request, formsets, inline_instances, obj=None):
|
||||
|
|
@ -88,7 +96,8 @@ class PolymorphicInlineSupportMixin(object):
|
|||
|
||||
for admin_formset in inline_admin_formsets:
|
||||
if isinstance(admin_formset.formset, BasePolymorphicModelFormSet):
|
||||
# Downcast the admin
|
||||
# This is a polymorphic formset, which belongs to our inline.
|
||||
# Downcast the admin wrapper that generates the form fields.
|
||||
admin_formset.__class__ = InlinePolymorphicAdminFormSet
|
||||
admin_formset.request = request
|
||||
admin_formset.obj = obj
|
||||
|
|
|
|||
|
|
@ -17,11 +17,10 @@ class PolymorphicParentInlineModelAdmin(InlineModelAdmin):
|
|||
"""
|
||||
A polymorphic inline, where each formset row can be a different form.
|
||||
|
||||
Note that
|
||||
Note that:
|
||||
|
||||
* Permissions are only checked on the base model.
|
||||
* The child inlines can't override the base model fields, only this parent inline can do that.
|
||||
* Child formset media is not yet processed.
|
||||
"""
|
||||
formset = BasePolymorphicInlineFormSet
|
||||
|
||||
|
|
@ -79,7 +78,7 @@ class PolymorphicParentInlineModelAdmin(InlineModelAdmin):
|
|||
|
||||
# Instead of completely redefining super().get_formset(), we use
|
||||
# the regular inlineformset_factory(), and amend that with our extra bits.
|
||||
# This is identical to what polymorphic_inlineformset_factory() does.
|
||||
# This code line is the essence of what polymorphic_inlineformset_factory() does.
|
||||
FormSet.child_forms = polymorphic_child_forms_factory(
|
||||
formset_children=self.get_formset_children(request, obj=obj)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class PolymorphicFormSetChild(object):
|
|||
Metadata to define the inline of a polymorphic child.
|
||||
Provide this information in the :func:`polymorphic_inlineformset_factory` construction.
|
||||
"""
|
||||
|
||||
def __init__(self, model, form=ModelForm, fields=None, exclude=None,
|
||||
formfield_callback=None, widgets=None, localized_fields=None,
|
||||
labels=None, help_texts=None, error_messages=None):
|
||||
|
|
@ -77,6 +78,9 @@ class PolymorphicFormSetChild(object):
|
|||
def polymorphic_child_forms_factory(formset_children, **kwargs):
|
||||
"""
|
||||
Construct the forms for the formset children.
|
||||
This is mostly used internally, and rarely needs to be used by external projects.
|
||||
When using the factory methods (:func:`polymorphic_inlineformset_factory`),
|
||||
this feature is called already for you.
|
||||
"""
|
||||
child_forms = OrderedDict()
|
||||
|
||||
|
|
@ -97,6 +101,7 @@ class BasePolymorphicModelFormSet(BaseModelFormSet):
|
|||
note that the ID field will no longer be named ``model_ptr``,
|
||||
but just appear as ``id``.
|
||||
"""
|
||||
|
||||
# Assigned by the factory
|
||||
child_forms = OrderedDict()
|
||||
|
||||
|
|
@ -191,6 +196,9 @@ class BasePolymorphicModelFormSet(BaseModelFormSet):
|
|||
super(BasePolymorphicModelFormSet, self).add_fields(form, index)
|
||||
|
||||
def get_form_class(self, model):
|
||||
"""
|
||||
Return the proper form class for the given model.
|
||||
"""
|
||||
if not self.child_forms:
|
||||
raise ImproperlyConfigured("No 'child_forms' defined in {0}".format(self.__class__.__name__))
|
||||
return self.child_forms[model]
|
||||
|
|
|
|||
Loading…
Reference in New Issue