forms.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. from django import forms
  2. from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
  3. from django.utils.html import mark_safe
  4. from netbox.preferences import PREFERENCES
  5. from utilities.forms import BootstrapMixin, DateTimePicker, StaticSelect
  6. from utilities.utils import flatten_dict
  7. from .models import Token, UserConfig
  8. class LoginForm(BootstrapMixin, AuthenticationForm):
  9. pass
  10. class PasswordChangeForm(BootstrapMixin, DjangoPasswordChangeForm):
  11. pass
  12. class UserConfigFormMetaclass(forms.models.ModelFormMetaclass):
  13. def __new__(mcs, name, bases, attrs):
  14. # Emulate a declared field for each supported user preference
  15. preference_fields = {}
  16. for field_name, preference in PREFERENCES.items():
  17. description = f'{preference.description}<br />' if preference.description else ''
  18. help_text = f'{description}<code>{field_name}</code>'
  19. field_kwargs = {
  20. 'label': preference.label,
  21. 'choices': preference.choices,
  22. 'help_text': mark_safe(help_text),
  23. 'coerce': preference.coerce,
  24. 'required': False,
  25. 'widget': StaticSelect,
  26. }
  27. preference_fields[field_name] = forms.TypedChoiceField(**field_kwargs)
  28. attrs.update(preference_fields)
  29. return super().__new__(mcs, name, bases, attrs)
  30. class UserConfigForm(BootstrapMixin, forms.ModelForm, metaclass=UserConfigFormMetaclass):
  31. fieldsets = (
  32. ('User Interface', (
  33. 'pagination.per_page',
  34. 'pagination.placement',
  35. 'ui.colormode',
  36. )),
  37. ('Miscellaneous', (
  38. 'data_format',
  39. )),
  40. )
  41. # List of clearable preferences
  42. pk = forms.MultipleChoiceField(
  43. choices=[],
  44. required=False
  45. )
  46. class Meta:
  47. model = UserConfig
  48. fields = ()
  49. def __init__(self, *args, instance=None, **kwargs):
  50. # Get initial data from UserConfig instance
  51. initial_data = flatten_dict(instance.data)
  52. kwargs['initial'] = initial_data
  53. super().__init__(*args, instance=instance, **kwargs)
  54. # Compile clearable preference choices
  55. self.fields['pk'].choices = (
  56. (f'tables.{table_name}', '') for table_name in instance.data.get('tables', [])
  57. )
  58. def save(self, *args, **kwargs):
  59. # Set UserConfig data
  60. for pref_name, value in self.cleaned_data.items():
  61. if pref_name == 'pk':
  62. continue
  63. self.instance.set(pref_name, value, commit=False)
  64. # Clear selected preferences
  65. for preference in self.cleaned_data['pk']:
  66. self.instance.clear(preference)
  67. return super().save(*args, **kwargs)
  68. @property
  69. def plugin_fields(self):
  70. return [
  71. name for name in self.fields.keys() if name.startswith('plugins.')
  72. ]
  73. class TokenForm(BootstrapMixin, forms.ModelForm):
  74. key = forms.CharField(
  75. required=False,
  76. help_text="If no key is provided, one will be generated automatically."
  77. )
  78. class Meta:
  79. model = Token
  80. fields = [
  81. 'key', 'write_enabled', 'expires', 'description',
  82. ]
  83. widgets = {
  84. 'expires': DateTimePicker(),
  85. }