array.py 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. from django import forms
  2. from django.contrib.postgres.forms import SimpleArrayField
  3. from django.utils.safestring import mark_safe
  4. from django.utils.translation import gettext_lazy as _
  5. from utilities.data import ranges_to_string, string_to_ranges
  6. from ..utils import parse_numeric_range
  7. __all__ = (
  8. 'NumericArrayField',
  9. 'NumericRangeArrayField',
  10. )
  11. class NumericArrayField(SimpleArrayField):
  12. def clean(self, value):
  13. if value and not self.to_python(value):
  14. raise forms.ValidationError(
  15. _("Invalid list ({value}). Must be numeric and ranges must be in ascending order.").format(value=value)
  16. )
  17. return super().clean(value)
  18. def to_python(self, value):
  19. if not value:
  20. return []
  21. if isinstance(value, str):
  22. value = ','.join([str(n) for n in parse_numeric_range(value)])
  23. return super().to_python(value)
  24. class NumericRangeArrayField(forms.CharField):
  25. """
  26. A field which allows for array of numeric ranges:
  27. Example: 1-5,10,20-30
  28. """
  29. def __init__(self, *args, help_text='', **kwargs):
  30. if not help_text:
  31. help_text = mark_safe(
  32. _(
  33. "Specify one or more individual numbers or numeric ranges separated by commas. Example: {example}"
  34. ).format(example="<code>1-5,10,20-30</code>")
  35. )
  36. super().__init__(*args, help_text=help_text, **kwargs)
  37. def clean(self, value):
  38. if value and not self.to_python(value):
  39. raise forms.ValidationError(
  40. _("Invalid ranges ({value}). Must be a range of integers in ascending order.").format(value=value)
  41. )
  42. return super().clean(value)
  43. def prepare_value(self, value):
  44. if isinstance(value, str):
  45. return value
  46. return ranges_to_string(value)
  47. def to_python(self, value):
  48. return string_to_ranges(value)