misc.py 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. from django import forms
  2. __all__ = (
  3. 'ArrayWidget',
  4. 'ChoicesWidget',
  5. 'ClearableFileInput',
  6. 'MarkdownWidget',
  7. 'NumberWithOptions',
  8. 'SlugWidget',
  9. )
  10. class ClearableFileInput(forms.ClearableFileInput):
  11. """
  12. Override Django's stock ClearableFileInput with a custom template.
  13. """
  14. template_name = 'widgets/clearable_file_input.html'
  15. class MarkdownWidget(forms.Textarea):
  16. """
  17. Provide a live preview for Markdown-formatted content.
  18. """
  19. template_name = 'widgets/markdown_input.html'
  20. def __init__(self, attrs=None):
  21. # Markdown fields should use monospace font
  22. default_attrs = {
  23. "class": "font-monospace",
  24. }
  25. if attrs:
  26. default_attrs.update(attrs)
  27. super().__init__(default_attrs)
  28. class NumberWithOptions(forms.NumberInput):
  29. """
  30. Number field with a dropdown pre-populated with common values for convenience.
  31. """
  32. template_name = 'widgets/number_with_options.html'
  33. def __init__(self, options, attrs=None):
  34. self.options = options
  35. super().__init__(attrs)
  36. def get_context(self, name, value, attrs):
  37. context = super().get_context(name, value, attrs)
  38. context['widget']['options'] = self.options
  39. return context
  40. class SlugWidget(forms.TextInput):
  41. """
  42. Subclass TextInput and add a slug regeneration button next to the form field.
  43. """
  44. template_name = 'widgets/sluginput.html'
  45. class ArrayWidget(forms.Textarea):
  46. """
  47. Render each item of an array on a new line within a textarea for easy editing/
  48. """
  49. def format_value(self, value):
  50. if value is None or not len(value):
  51. return None
  52. return '\n'.join(value)
  53. class ChoicesWidget(forms.Textarea):
  54. """
  55. Render each key-value pair of a dictionary on a new line within a textarea for easy editing.
  56. """
  57. def format_value(self, value):
  58. if not value:
  59. return None
  60. if type(value) is list:
  61. return '\n'.join([f'{k}:{v}' for k, v in value])
  62. return value