Coverage for apis_core/generic/forms/fields.py: 43%

35 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-09-03 06:15 +0000

1from django.core.exceptions import ValidationError 

2from django.forms import ModelChoiceField, MultiValueField, MultiWidget 

3from django.utils.translation import gettext as _ 

4 

5from apis_core.uris.utils import create_object_from_uri 

6 

7 

8class ModelImportChoiceField(ModelChoiceField): 

9 def to_python(self, value): 

10 result = None 

11 if value.startswith(("http://", "https://")): 

12 try: 

13 result = create_object_from_uri( 

14 value, self.queryset.model, raise_on_fail=True 

15 ) 

16 except Exception as e: 

17 raise ValidationError( 

18 _("Could not import %(value)s: %(exception)s"), 

19 params={"value": value, "exception": e}, 

20 ) 

21 return result or super().to_python(value) 

22 

23 

24class RowColumnMultiWidget(MultiWidget): 

25 """ 

26 A custom MultiWidget that is meant to be used with the 

27 RowColumnMultiValueField. The widget takes a list of widgets 

28 as a parameter and displays those widgets in columns in one row. 

29 The `labels` parameter is used to add a separate label to the 

30 individual widgets. 

31 """ 

32 

33 template_name = "widgets/row_column_multiwidget.html" 

34 use_fieldset = False 

35 

36 def __init__(self, widgets, labels=[], attrs=None): 

37 self.labels = labels 

38 super().__init__(widgets, attrs) 

39 

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

41 ctx = super().get_context(name, value, attrs) 

42 for widget in ctx["widget"]["subwidgets"]: 

43 if self.labels: 

44 widget["label"] = self.labels.pop(0) 

45 return ctx 

46 

47 def decompress(self, value): 

48 if value: 

49 return value 

50 return [] 

51 

52 

53class RowColumnMultiValueField(MultiValueField): 

54 """ 

55 This is a custom MultiValueField that simply shows multiple form 

56 fields in a row. The form fields are passed to the constructor and 

57 the corresponding RowColumnMultiWidget simply iterates through all 

58 the fields and shows them in rows. 

59 Additionaly it is possible to pass a list of `labels` that are then 

60 also passed on to the widget, which uses those to add a separate 

61 label to the individual widgets. 

62 """ 

63 

64 def __init__(self, fields, labels=[], *args, **kwargs): 

65 kwargs["widget"] = RowColumnMultiWidget( 

66 widgets=[f.widget for f in fields], labels=labels 

67 ) 

68 super().__init__(fields, *args, **kwargs) 

69 

70 def compress(self, data_list): 

71 return data_list