django-polymorphic/polymorphic/contrib/extra_views.py

141 lines
4.0 KiB
Python

"""
The ``extra_views.formsets`` provides a simple way to handle formsets.
The ``extra_views.advanced`` provides a method to combine that with a create/update form.
This package provides classes that support both options for polymorphic formsets.
"""
import extra_views
from django.core.exceptions import ImproperlyConfigured
from polymorphic.formsets import (
BasePolymorphicInlineFormSet,
BasePolymorphicModelFormSet,
polymorphic_child_forms_factory,
)
__all__ = (
"PolymorphicFormSetView",
"PolymorphicInlineFormSetView",
"PolymorphicInlineFormSet",
)
class PolymorphicFormSetMixin(object):
"""
Internal Mixin, that provides polymorphic integration with the ``extra_views`` package.
"""
formset_class = BasePolymorphicModelFormSet
#: Default 0 extra forms
factory_kwargs = {"extra": 0}
#: Define the children
# :type: list[PolymorphicFormSetChild]
formset_children = None
def get_formset_children(self):
"""
:rtype: list[PolymorphicFormSetChild]
"""
if not self.formset_children:
raise ImproperlyConfigured(
"Define 'formset_children' as list of `PolymorphicFormSetChild`"
)
return self.formset_children
def get_formset_child_kwargs(self):
return {}
def get_formset(self):
"""
Returns the formset class from the inline formset factory
"""
# Implementation detail:
# Since `polymorphic_modelformset_factory` and `polymorphic_inlineformset_factory` mainly
# reuse the standard factories, and then add `child_forms`, the same can be done here.
# This makes sure the base class construction is completely honored.
FormSet = super(PolymorphicFormSetMixin, self).get_formset()
FormSet.child_forms = polymorphic_child_forms_factory(
self.get_formset_children(), **self.get_formset_child_kwargs()
)
return FormSet
class PolymorphicFormSetView(PolymorphicFormSetMixin, extra_views.ModelFormSetView):
"""
A view that displays a single polymorphic formset.
.. code-block:: python
from polymorphic.formsets import PolymorphicFormSetChild
class ItemsView(PolymorphicFormSetView):
model = Item
formset_children = [
PolymorphicFormSetChild(ItemSubclass1),
PolymorphicFormSetChild(ItemSubclass2),
]
"""
formset_class = BasePolymorphicModelFormSet
class PolymorphicInlineFormSetView(
PolymorphicFormSetMixin, extra_views.InlineFormSetView
):
"""
A view that displays a single polymorphic formset - with one parent object.
This is a variation of the :mod:`extra_views` package classes for django-polymorphic.
.. code-block:: python
from polymorphic.formsets import PolymorphicFormSetChild
class OrderItemsView(PolymorphicInlineFormSetView):
model = Order
inline_model = Item
formset_children = [
PolymorphicFormSetChild(ItemSubclass1),
PolymorphicFormSetChild(ItemSubclass2),
]
"""
formset_class = BasePolymorphicInlineFormSet
class PolymorphicInlineFormSet(
PolymorphicFormSetMixin, extra_views.InlineFormSetFactory
):
"""
An inline to add to the ``inlines`` of
the :class:`~extra_views.advanced.CreateWithInlinesView`
and :class:`~extra_views.advanced.UpdateWithInlinesView` class.
.. code-block:: python
from polymorphic.formsets import PolymorphicFormSetChild
class ItemsInline(PolymorphicInlineFormSet):
model = Item
formset_children = [
PolymorphicFormSetChild(ItemSubclass1),
PolymorphicFormSetChild(ItemSubclass2),
]
class OrderCreateView(CreateWithInlinesView):
model = Order
inlines = [ItemsInline]
def get_success_url(self):
return self.object.get_absolute_url()
"""
formset_class = BasePolymorphicInlineFormSet