mirror of https://github.com/sgoudham/Enso-Bot.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.7 KiB
Python
118 lines
3.7 KiB
Python
5 years ago
|
import warnings
|
||
|
|
||
|
from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange
|
||
|
|
||
|
from django import forms
|
||
|
from django.core import exceptions
|
||
|
from django.forms.widgets import HiddenInput, MultiWidget
|
||
|
from django.utils.deprecation import RemovedInDjango31Warning
|
||
|
from django.utils.translation import gettext_lazy as _
|
||
|
|
||
|
__all__ = [
|
||
|
'BaseRangeField', 'IntegerRangeField', 'DecimalRangeField',
|
||
|
'DateTimeRangeField', 'DateRangeField', 'FloatRangeField',
|
||
|
'HiddenRangeWidget', 'RangeWidget',
|
||
|
]
|
||
|
|
||
|
|
||
|
class RangeWidget(MultiWidget):
|
||
|
def __init__(self, base_widget, attrs=None):
|
||
|
widgets = (base_widget, base_widget)
|
||
|
super().__init__(widgets, attrs)
|
||
|
|
||
|
def decompress(self, value):
|
||
|
if value:
|
||
|
return (value.lower, value.upper)
|
||
|
return (None, None)
|
||
|
|
||
|
|
||
|
class HiddenRangeWidget(RangeWidget):
|
||
|
"""A widget that splits input into two <input type="hidden"> inputs."""
|
||
|
def __init__(self, attrs=None):
|
||
|
super().__init__(HiddenInput, attrs)
|
||
|
|
||
|
|
||
|
class BaseRangeField(forms.MultiValueField):
|
||
|
default_error_messages = {
|
||
|
'invalid': _('Enter two valid values.'),
|
||
|
'bound_ordering': _('The start of the range must not exceed the end of the range.'),
|
||
|
}
|
||
|
hidden_widget = HiddenRangeWidget
|
||
|
|
||
|
def __init__(self, **kwargs):
|
||
|
if 'widget' not in kwargs:
|
||
|
kwargs['widget'] = RangeWidget(self.base_field.widget)
|
||
|
if 'fields' not in kwargs:
|
||
|
kwargs['fields'] = [self.base_field(required=False), self.base_field(required=False)]
|
||
|
kwargs.setdefault('required', False)
|
||
|
kwargs.setdefault('require_all_fields', False)
|
||
|
super().__init__(**kwargs)
|
||
|
|
||
|
def prepare_value(self, value):
|
||
|
lower_base, upper_base = self.fields
|
||
|
if isinstance(value, self.range_type):
|
||
|
return [
|
||
|
lower_base.prepare_value(value.lower),
|
||
|
upper_base.prepare_value(value.upper),
|
||
|
]
|
||
|
if value is None:
|
||
|
return [
|
||
|
lower_base.prepare_value(None),
|
||
|
upper_base.prepare_value(None),
|
||
|
]
|
||
|
return value
|
||
|
|
||
|
def compress(self, values):
|
||
|
if not values:
|
||
|
return None
|
||
|
lower, upper = values
|
||
|
if lower is not None and upper is not None and lower > upper:
|
||
|
raise exceptions.ValidationError(
|
||
|
self.error_messages['bound_ordering'],
|
||
|
code='bound_ordering',
|
||
|
)
|
||
|
try:
|
||
|
range_value = self.range_type(lower, upper)
|
||
|
except TypeError:
|
||
|
raise exceptions.ValidationError(
|
||
|
self.error_messages['invalid'],
|
||
|
code='invalid',
|
||
|
)
|
||
|
else:
|
||
|
return range_value
|
||
|
|
||
|
|
||
|
class IntegerRangeField(BaseRangeField):
|
||
|
default_error_messages = {'invalid': _('Enter two whole numbers.')}
|
||
|
base_field = forms.IntegerField
|
||
|
range_type = NumericRange
|
||
|
|
||
|
|
||
|
class DecimalRangeField(BaseRangeField):
|
||
|
default_error_messages = {'invalid': _('Enter two numbers.')}
|
||
|
base_field = forms.DecimalField
|
||
|
range_type = NumericRange
|
||
|
|
||
|
|
||
|
class FloatRangeField(DecimalRangeField):
|
||
|
base_field = forms.FloatField
|
||
|
|
||
|
def __init__(self, **kwargs):
|
||
|
warnings.warn(
|
||
|
'FloatRangeField is deprecated in favor of DecimalRangeField.',
|
||
|
RemovedInDjango31Warning, stacklevel=2,
|
||
|
)
|
||
|
super().__init__(**kwargs)
|
||
|
|
||
|
|
||
|
class DateTimeRangeField(BaseRangeField):
|
||
|
default_error_messages = {'invalid': _('Enter two valid date/times.')}
|
||
|
base_field = forms.DateTimeField
|
||
|
range_type = DateTimeTZRange
|
||
|
|
||
|
|
||
|
class DateRangeField(BaseRangeField):
|
||
|
default_error_messages = {'invalid': _('Enter two valid dates.')}
|
||
|
base_field = forms.DateField
|
||
|
range_type = DateRange
|