Coverage for apis_core/generic/forms/__init__.py: 38%

64 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-22 07:51 +0000

1from crispy_forms.helper import FormHelper 

2from crispy_forms.layout import Submit 

3from dal import autocomplete 

4from django import forms 

5from django.contrib.contenttypes.models import ContentType 

6from django.urls import reverse 

7 

8from apis_core.generic.abc import GenericModel 

9from apis_core.generic.forms.fields import ModelImportChoiceField 

10 

11 

12class GenericImportForm(forms.Form): 

13 class Meta: 

14 fields = [] 

15 

16 def __init__(self, *args, **kwargs): 

17 super().__init__(*args, **kwargs) 

18 self.fields["url"] = ModelImportChoiceField( 

19 queryset=self.Meta.model.objects.all() 

20 ) 

21 ct = ContentType.objects.get_for_model(self.Meta.model) 

22 url = reverse("apis_core:generic:autocompleteexternalonly", args=[ct]) 

23 self.fields["url"].widget = autocomplete.ModelSelect2( 

24 url, attrs={"data-html": True, "data-tags": 1} 

25 ) 

26 self.fields["url"].widget.choices = self.fields["url"].choices 

27 self.helper = FormHelper() 

28 self.helper.add_input(Submit("submit", "Submit")) 

29 

30 

31class GenericFilterSetForm(forms.Form): 

32 """ 

33 FilterSet form for generic models 

34 Adds a submit button using the django crispy form helper 

35 Adds a `columns` selector that lists all the fields from 

36 the model 

37 """ 

38 

39 columns_exclude = [] 

40 

41 def __init__(self, *args, **kwargs): 

42 super().__init__(*args, **kwargs) 

43 

44 self.helper = FormHelper() 

45 self.helper.form_method = "GET" 

46 self.helper.add_input(Submit("submit", "Submit")) 

47 

48 def clean(self): 

49 self.cleaned_data = super().clean() 

50 self.cleaned_data.pop("columns", None) 

51 return self.cleaned_data 

52 

53 

54class GenericModelForm(forms.ModelForm): 

55 """ 

56 Model form for generic models 

57 Adds a submit button using the django crispy form helper 

58 and sets the ModelChoiceFields and ModelMultipleChoiceFields 

59 to use autocomplete replacement fields 

60 """ 

61 

62 class Meta: 

63 fields = "__all__" 

64 

65 def __init__(self, *args, **kwargs): 

66 super().__init__(*args, **kwargs) 

67 self.helper = FormHelper(self) 

68 self.helper.add_input(Submit("submit", "Submit")) 

69 

70 # override the fields pointing to other models, 

71 # to make them use the autocomplete widgets 

72 override_fieldtypes = { 

73 "ModelMultipleChoiceField": autocomplete.ModelSelect2Multiple, 

74 "ModelChoiceField": autocomplete.ModelSelect2, 

75 "ModelImportChoiceField": autocomplete.ModelSelect2, 

76 } 

77 for field in self.fields: 

78 clsname = self.fields[field].__class__.__name__ 

79 if clsname in override_fieldtypes.keys(): 

80 ct = ContentType.objects.get_for_model( 

81 self.fields[field]._queryset.model 

82 ) 

83 if issubclass(ct.model_class(), GenericModel): 

84 url = reverse("apis_core:generic:autocomplete", args=[ct]) 

85 self.fields[field].widget = override_fieldtypes[clsname]( 

86 url, attrs={"data-html": True} 

87 ) 

88 self.fields[field].widget.choices = self.fields[field].choices 

89 

90 

91class GenericMergeForm(forms.Form): 

92 def __init__(self, *args, **kwargs): 

93 super().__init__(*args, **kwargs) 

94 self.helper = FormHelper() 

95 self.helper.add_input(Submit("submit", "Merge")) 

96 

97 

98class GenericEnrichForm(forms.Form): 

99 def __init__(self, *args, **kwargs): 

100 data = kwargs.pop("data", {}) 

101 instance = kwargs.pop("instance", None) 

102 super().__init__(*args, **kwargs) 

103 for key, value in data.items(): 

104 update_key = f"update_{key}" 

105 self.fields[update_key] = forms.BooleanField( 

106 required=False, 

107 label=f"Update {key} from {getattr(instance, key)} to {value}", 

108 ) 

109 

110 self.fields[key] = forms.CharField(initial=value, required=False) 

111 self.fields[key].widget = self.fields[key].hidden_widget() 

112 self.helper = FormHelper() 

113 self.helper.add_input(Submit("submit", "Submit"))