Coverage for utilities/forms/fields/array.py: 42%
33 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1from django import forms
2from django.contrib.postgres.forms import SimpleArrayField
3from django.utils.safestring import mark_safe
4from django.utils.translation import gettext_lazy as _
6from utilities.data import ranges_to_string, string_to_ranges
8from ..utils import parse_numeric_range
10__all__ = (
11 'NumericArrayField',
12 'NumericRangeArrayField',
13)
16class NumericArrayField(SimpleArrayField):
18 def clean(self, value):
19 if value and not self.to_python(value):
20 raise forms.ValidationError(
21 _("Invalid list ({value}). Must be numeric and ranges must be in ascending order.").format(value=value)
22 )
23 return super().clean(value)
25 def to_python(self, value):
26 if not value:
27 return []
28 if isinstance(value, str):
29 value = ','.join([str(n) for n in parse_numeric_range(value)])
30 return super().to_python(value)
33class NumericRangeArrayField(forms.CharField):
34 """
35 A field which allows for array of numeric ranges:
36 Example: 1-5,10,20-30
37 """
38 def __init__(self, *args, help_text='', **kwargs):
39 if not help_text: 39 ↛ 45line 39 didn't jump to line 45 because the condition on line 39 was always true
40 help_text = mark_safe(
41 _(
42 "Specify one or more individual numbers or numeric ranges separated by commas. Example: {example}"
43 ).format(example="<code>1-5,10,20-30</code>")
44 )
45 super().__init__(*args, help_text=help_text, **kwargs)
47 def clean(self, value):
48 if value and not self.to_python(value):
49 raise forms.ValidationError(
50 _("Invalid ranges ({value}). Must be a range of integers in ascending order.").format(value=value)
51 )
52 return super().clean(value)
54 def prepare_value(self, value):
55 if isinstance(value, str):
56 return value
57 return ranges_to_string(value)
59 def to_python(self, value):
60 return string_to_ranges(value)