mixins.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from django import forms
  2. from django.utils.translation import gettext as _
  3. from core.models import ObjectType
  4. from extras.choices import *
  5. from extras.models import *
  6. from utilities.forms.fields import DynamicModelMultipleChoiceField
  7. __all__ = (
  8. 'ChangeLoggingMixin',
  9. 'CustomFieldsMixin',
  10. 'SavedFiltersMixin',
  11. 'TagsMixin',
  12. )
  13. class ChangeLoggingMixin(forms.Form):
  14. """
  15. Adds an optional field for recording a message on the resulting changelog record(s).
  16. """
  17. changelog_message = forms.CharField(
  18. required=False,
  19. max_length=200
  20. )
  21. class CustomFieldsMixin:
  22. """
  23. Extend a Form to include custom field support.
  24. Attributes:
  25. model: The model class
  26. """
  27. model = None
  28. def __init__(self, *args, **kwargs):
  29. self.custom_fields = {}
  30. self.custom_field_groups = {}
  31. super().__init__(*args, **kwargs)
  32. self._append_customfield_fields()
  33. def _get_content_type(self):
  34. """
  35. Return the ObjectType of the form's model.
  36. """
  37. if not getattr(self, 'model', None):
  38. raise NotImplementedError(_("{class_name} must specify a model class.").format(
  39. class_name=self.__class__.__name__
  40. ))
  41. return ObjectType.objects.get_for_model(self.model)
  42. def _get_custom_fields(self, content_type):
  43. return CustomField.objects.filter(object_types=content_type).exclude(
  44. ui_editable=CustomFieldUIEditableChoices.HIDDEN
  45. )
  46. def _get_form_field(self, customfield):
  47. return customfield.to_form_field()
  48. def _append_customfield_fields(self):
  49. """
  50. Append form fields for all CustomFields assigned to this object type.
  51. """
  52. for customfield in self._get_custom_fields(self._get_content_type()):
  53. field_name = f'cf_{customfield.name}'
  54. self.fields[field_name] = self._get_form_field(customfield)
  55. # Annotate the field in the list of CustomField form fields
  56. self.custom_fields[field_name] = customfield
  57. if customfield.group_name not in self.custom_field_groups:
  58. self.custom_field_groups[customfield.group_name] = []
  59. self.custom_field_groups[customfield.group_name].append(field_name)
  60. class SavedFiltersMixin(forms.Form):
  61. filter_id = DynamicModelMultipleChoiceField(
  62. queryset=SavedFilter.objects.all(),
  63. required=False,
  64. label=_('Saved Filter'),
  65. query_params={
  66. 'usable': True,
  67. }
  68. )
  69. def __init__(self, *args, **kwargs):
  70. super().__init__(*args, **kwargs)
  71. # Limit saved filters to those applicable to the form's model
  72. if hasattr(self, 'model'):
  73. object_type = ObjectType.objects.get_for_model(self.model)
  74. self.fields['filter_id'].widget.add_query_params({
  75. 'object_type_id': object_type.pk,
  76. })
  77. class TagsMixin(forms.Form):
  78. tags = DynamicModelMultipleChoiceField(
  79. queryset=Tag.objects.all(),
  80. required=False,
  81. label=_('Tags'),
  82. )
  83. def __init__(self, *args, **kwargs):
  84. super().__init__(*args, **kwargs)
  85. # Limit tags to those applicable to the object type
  86. object_type = ObjectType.objects.get_for_model(self._meta.model)
  87. if object_type and hasattr(self.fields['tags'].widget, 'add_query_param'):
  88. self.fields['tags'].widget.add_query_param('for_object_type_id', object_type.pk)