Coverage for utilities/forms/widgets/misc.py: 58%

40 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from django import forms 

2 

3__all__ = ( 

4 'ArrayWidget', 

5 'ChoicesWidget', 

6 'ClearableFileInput', 

7 'MarkdownWidget', 

8 'NumberWithOptions', 

9 'SlugWidget', 

10) 

11 

12 

13class ClearableFileInput(forms.ClearableFileInput): 

14 """ 

15 Override Django's stock ClearableFileInput with a custom template. 

16 """ 

17 template_name = 'widgets/clearable_file_input.html' 

18 

19 

20class MarkdownWidget(forms.Textarea): 

21 """ 

22 Provide a live preview for Markdown-formatted content. 

23 """ 

24 template_name = 'widgets/markdown_input.html' 

25 

26 def __init__(self, attrs=None): 

27 # Markdown fields should use monospace font 

28 default_attrs = { 

29 "class": "font-monospace", 

30 } 

31 if attrs: 31 ↛ 32line 31 didn't jump to line 32 because the condition on line 31 was never true

32 default_attrs.update(attrs) 

33 

34 super().__init__(default_attrs) 

35 

36 

37class NumberWithOptions(forms.NumberInput): 

38 """ 

39 Number field with a dropdown pre-populated with common values for convenience. 

40 """ 

41 template_name = 'widgets/number_with_options.html' 

42 

43 def __init__(self, options, attrs=None): 

44 self.options = options 

45 super().__init__(attrs) 

46 

47 def get_context(self, name, value, attrs): 

48 context = super().get_context(name, value, attrs) 

49 context['widget']['options'] = self.options 

50 return context 

51 

52 

53class SlugWidget(forms.TextInput): 

54 """ 

55 Subclass TextInput and add a slug regeneration button next to the form field. 

56 """ 

57 template_name = 'widgets/sluginput.html' 

58 

59 def __init__(self, attrs=None): 

60 local_attrs = {} if attrs is None else attrs.copy() 

61 if 'class' in local_attrs: 61 ↛ 62line 61 didn't jump to line 62 because the condition on line 61 was never true

62 local_attrs['class'] = f"{local_attrs['class']} slug-field" 

63 else: 

64 local_attrs['class'] = 'slug-field' 

65 super().__init__(local_attrs) 

66 

67 

68class ArrayWidget(forms.Textarea): 

69 """ 

70 Render each item of an array on a new line within a textarea for easy editing/ 

71 """ 

72 def format_value(self, value): 

73 if value is None or not len(value): 

74 return None 

75 return '\n'.join(value) 

76 

77 

78class ChoicesWidget(forms.Textarea): 

79 """ 

80 Render each key-value pair of a dictionary on a new line within a textarea for easy editing. 

81 """ 

82 def format_value(self, value): 

83 if not value: 

84 return None 

85 if type(value) is list: 

86 return '\n'.join([f'{k}:{v}' for k, v in value]) 

87 return value