Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/contrib/postgres/forms/ranges.py: 52%
62 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange
3from django import forms
4from django.core import exceptions
5from django.forms.widgets import HiddenInput, MultiWidget
6from django.utils.translation import gettext_lazy as _
8__all__ = [
9 "BaseRangeField",
10 "IntegerRangeField",
11 "DecimalRangeField",
12 "DateTimeRangeField",
13 "DateRangeField",
14 "HiddenRangeWidget",
15 "RangeWidget",
16]
19class RangeWidget(MultiWidget):
20 def __init__(self, base_widget, attrs=None):
21 widgets = (base_widget, base_widget)
22 super().__init__(widgets, attrs)
24 def decompress(self, value):
25 if value:
26 return (value.lower, value.upper)
27 return (None, None)
30class HiddenRangeWidget(RangeWidget):
31 """A widget that splits input into two <input type="hidden"> inputs."""
33 def __init__(self, attrs=None):
34 super().__init__(HiddenInput, attrs)
37class BaseRangeField(forms.MultiValueField):
38 default_error_messages = {
39 "invalid": _("Enter two valid values."),
40 "bound_ordering": _(
41 "The start of the range must not exceed the end of the range."
42 ),
43 }
44 hidden_widget = HiddenRangeWidget
46 def __init__(self, **kwargs):
47 if "widget" not in kwargs:
48 kwargs["widget"] = RangeWidget(self.base_field.widget)
49 if "fields" not in kwargs:
50 kwargs["fields"] = [
51 self.base_field(required=False),
52 self.base_field(required=False),
53 ]
54 kwargs.setdefault("required", False)
55 kwargs.setdefault("require_all_fields", False)
56 super().__init__(**kwargs)
58 def prepare_value(self, value):
59 lower_base, upper_base = self.fields
60 if isinstance(value, self.range_type):
61 return [
62 lower_base.prepare_value(value.lower),
63 upper_base.prepare_value(value.upper),
64 ]
65 if value is None:
66 return [
67 lower_base.prepare_value(None),
68 upper_base.prepare_value(None),
69 ]
70 return value
72 def compress(self, values):
73 if not values:
74 return None
75 lower, upper = values
76 if lower is not None and upper is not None and lower > upper:
77 raise exceptions.ValidationError(
78 self.error_messages["bound_ordering"],
79 code="bound_ordering",
80 )
81 try:
82 range_value = self.range_type(lower, upper)
83 except TypeError:
84 raise exceptions.ValidationError(
85 self.error_messages["invalid"],
86 code="invalid",
87 )
88 else:
89 return range_value
92class IntegerRangeField(BaseRangeField):
93 default_error_messages = {"invalid": _("Enter two whole numbers.")}
94 base_field = forms.IntegerField
95 range_type = NumericRange
98class DecimalRangeField(BaseRangeField):
99 default_error_messages = {"invalid": _("Enter two numbers.")}
100 base_field = forms.DecimalField
101 range_type = NumericRange
104class DateTimeRangeField(BaseRangeField):
105 default_error_messages = {"invalid": _("Enter two valid date/times.")}
106 base_field = forms.DateTimeField
107 range_type = DateTimeTZRange
110class DateRangeField(BaseRangeField):
111 default_error_messages = {"invalid": _("Enter two valid dates.")}
112 base_field = forms.DateField
113 range_type = DateRange