1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
from django.contrib.contenttypes.admin import GenericInlineModelAdmin
from django.contrib.contenttypes.models import ContentType
from django.utils.functional import cached_property
from polymorphic.formsets import (
BaseGenericPolymorphicInlineFormSet,
GenericPolymorphicFormSetChild,
polymorphic_child_forms_factory,
)
from .inlines import PolymorphicInlineModelAdmin
class GenericPolymorphicInlineModelAdmin(PolymorphicInlineModelAdmin, GenericInlineModelAdmin):
"""
Base class for variation of inlines based on generic foreign keys.
"""
#: The formset class
formset = BaseGenericPolymorphicInlineFormSet
def get_formset(self, request, obj=None, **kwargs):
"""
Construct the generic inline formset class.
"""
# Construct the FormSet class. This is almost the same as parent version,
# except that a different super is called so generic_inlineformset_factory() is used.
# NOTE that generic_inlineformset_factory() also makes sure the GFK fields are excluded in the form.
FormSet = GenericInlineModelAdmin.get_formset(self, request, obj=obj, **kwargs)
FormSet.child_forms = polymorphic_child_forms_factory(
formset_children=self.get_formset_children(request, obj=obj)
)
return FormSet
class Child(PolymorphicInlineModelAdmin.Child):
"""
Variation for generic inlines.
"""
# Make sure that the GFK fields are excluded from the child forms
formset_child = GenericPolymorphicFormSetChild
ct_field = "content_type"
ct_fk_field = "object_id"
@cached_property
def content_type(self):
"""
Expose the ContentType that the child relates to.
This can be used for the ``polymorphic_ctype`` field.
"""
return ContentType.objects.get_for_model(self.model, for_concrete_model=False)
def get_formset_child(self, request, obj=None, **kwargs):
# Similar to GenericInlineModelAdmin.get_formset(),
# make sure the GFK is automatically excluded from the form
defaults = {"ct_field": self.ct_field, "fk_field": self.ct_fk_field}
defaults.update(kwargs)
return super(GenericPolymorphicInlineModelAdmin.Child, self).get_formset_child(
request, obj=obj, **defaults
)
class GenericStackedPolymorphicInline(GenericPolymorphicInlineModelAdmin):
"""
The stacked layout for generic inlines.
"""
#: The default template to use.
template = "admin/polymorphic/edit_inline/stacked.html"
|