from django.contrib.contenttypes.models import ContentType from extras.models import * from extras.choices import CustomFieldVisibilityChoices __all__ = ( 'CustomFieldsMixin', ) class CustomFieldsMixin: """ Extend a Form to include custom field support. Attributes: model: The model class """ model = None def __init__(self, *args, **kwargs): self.custom_fields = {} self.custom_field_groups = {} super().__init__(*args, **kwargs) self._append_customfield_fields() def _get_content_type(self): """ Return the ContentType of the form's model. """ if not getattr(self, 'model', None): raise NotImplementedError(f"{self.__class__.__name__} must specify a model class.") return ContentType.objects.get_for_model(self.model) def _get_custom_fields(self, content_type): return CustomField.objects.filter(content_types=content_type).exclude( ui_visibility=CustomFieldVisibilityChoices.VISIBILITY_HIDDEN ) def _get_form_field(self, customfield): return customfield.to_form_field() def _append_customfield_fields(self): """ Append form fields for all CustomFields assigned to this object type. """ for customfield in self._get_custom_fields(self._get_content_type()): if customfield.ui_visibility == CustomFieldVisibilityChoices.VISIBILITY_HIDDEN: continue field_name = f'cf_{customfield.name}' self.fields[field_name] = self._get_form_field(customfield) # Annotate the field in the list of CustomField form fields self.custom_fields[field_name] = customfield if customfield.group_name not in self.custom_field_groups: self.custom_field_groups[customfield.group_name] = [] self.custom_field_groups[customfield.group_name].append(field_name)