"""This module contains classes used for admin integration."""
from typing import Any, Dict, List, Optional, Union
from django.contrib import admin
from django.contrib.admin.options import InlineModelAdmin, ModelAdmin
from django.forms.models import BaseInlineFormSet
from django.utils.safestring import mark_safe
from eav.models import Attribute, EnumGroup, EnumValue, Value
_FIELDSET_TYPE = List[Union[str, Dict[str, Any]]] # type: ignore[misc]
[docs]class BaseEntityAdmin(ModelAdmin):
"""Custom admin model to support dynamic EAV fieldsets.
Overrides the default rendering of the change form in the Django admin to
dynamically integrate EAV fields into the form fieldsets. This approach
allows EAV attributes to be rendered alongside standard model fields within
the admin interface.
Attributes:
eav_fieldset_title (str): Title for the dynamically added EAV fieldset.
eav_fieldset_description (str): Optional description for the EAV fieldset.
"""
eav_fieldset_title: str = "EAV Attributes"
eav_fieldset_description: Optional[str] = None
def _get_eav_fields(self, instance) -> List[str]:
"""Retrieves a list of EAV field slugs for the given instance.
Args:
instance: The model instance for which EAV fields are determined.
Returns:
A list of strings representing the slugs of EAV fields.
"""
entity = getattr(instance, instance._eav_config_cls.eav_attr)
return list(entity.get_all_attributes().values_list('slug', flat=True))
def _get_eav_fieldset(self, eav_fields) -> _FIELDSET_TYPE:
"""Constructs an EAV Attributes fieldset for inclusion in admin form fieldsets.
Generates a list representing a fieldset specifically for Entity-Attribute-Value (EAV) fields,
intended to be appended to the admin form's fieldsets configuration. This facilitates the
dynamic inclusion of EAV fields within the Django admin interface by creating a designated
section for these attributes.
Args:
eav_fields (List[str]): A list of slugs representing the EAV fields to be included
in the EAV Attributes fieldset.
"""
return [
self.eav_fieldset_title,
{'fields': eav_fields, 'description': self.eav_fieldset_description},
]
[docs]class BaseEntityInline(InlineModelAdmin):
"""
Inline model admin that works correctly with EAV attributes. You should mix
in the standard ``StackedInline`` or ``TabularInline`` classes in order to
define formset representation, e.g.::
class ItemInline(BaseEntityInline, StackedInline):
model = Item
form = forms.ItemForm
.. warning:: ``TabularInline`` does *not* work out of the box. There is,
however, a patched template ``admin/edit_inline/tabular.html`` bundled
with EAV-Django. You can copy or symlink the ``admin`` directory to
your templates search path (see Django documentation).
"""
formset = BaseEntityInlineFormSet
[docs] def get_fieldsets(self, request, obj=None):
if self.declared_fieldsets:
return self.declared_fieldsets
formset = self.get_formset(request)
fk_name = self.fk_name or formset.fk.name
kw = {fk_name: obj} if obj else {}
instance = self.model(**kw)
form = formset.form(request.POST, instance=instance)
return [(None, {'fields': form.fields.keys()})]
[docs]class AttributeAdmin(ModelAdmin):
list_display = ('name', 'slug', 'datatype', 'description')
prepopulated_fields = {'slug': ('name',)}
admin.site.register(Attribute, AttributeAdmin)
admin.site.register(EnumValue)
admin.site.register(EnumGroup)
admin.site.register(Value)