Ajoutez des fichiers projet.
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
from .array import * # NOQA
|
||||
from .hstore import * # NOQA
|
||||
from .ranges import * # NOQA
|
234
venv/Lib/site-packages/django/contrib/postgres/forms/array.py
Normal file
234
venv/Lib/site-packages/django/contrib/postgres/forms/array.py
Normal file
@@ -0,0 +1,234 @@
|
||||
import copy
|
||||
from itertools import chain
|
||||
|
||||
from django import forms
|
||||
from django.contrib.postgres.validators import (
|
||||
ArrayMaxLengthValidator, ArrayMinLengthValidator,
|
||||
)
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from ..utils import prefix_validation_error
|
||||
|
||||
|
||||
class SimpleArrayField(forms.CharField):
|
||||
default_error_messages = {
|
||||
'item_invalid': _('Item %(nth)s in the array did not validate:'),
|
||||
}
|
||||
|
||||
def __init__(self, base_field, *, delimiter=',', max_length=None, min_length=None, **kwargs):
|
||||
self.base_field = base_field
|
||||
self.delimiter = delimiter
|
||||
super().__init__(**kwargs)
|
||||
if min_length is not None:
|
||||
self.min_length = min_length
|
||||
self.validators.append(ArrayMinLengthValidator(int(min_length)))
|
||||
if max_length is not None:
|
||||
self.max_length = max_length
|
||||
self.validators.append(ArrayMaxLengthValidator(int(max_length)))
|
||||
|
||||
def clean(self, value):
|
||||
value = super().clean(value)
|
||||
return [self.base_field.clean(val) for val in value]
|
||||
|
||||
def prepare_value(self, value):
|
||||
if isinstance(value, list):
|
||||
return self.delimiter.join(str(self.base_field.prepare_value(v)) for v in value)
|
||||
return value
|
||||
|
||||
def to_python(self, value):
|
||||
if isinstance(value, list):
|
||||
items = value
|
||||
elif value:
|
||||
items = value.split(self.delimiter)
|
||||
else:
|
||||
items = []
|
||||
errors = []
|
||||
values = []
|
||||
for index, item in enumerate(items):
|
||||
try:
|
||||
values.append(self.base_field.to_python(item))
|
||||
except ValidationError as error:
|
||||
errors.append(prefix_validation_error(
|
||||
error,
|
||||
prefix=self.error_messages['item_invalid'],
|
||||
code='item_invalid',
|
||||
params={'nth': index + 1},
|
||||
))
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
return values
|
||||
|
||||
def validate(self, value):
|
||||
super().validate(value)
|
||||
errors = []
|
||||
for index, item in enumerate(value):
|
||||
try:
|
||||
self.base_field.validate(item)
|
||||
except ValidationError as error:
|
||||
errors.append(prefix_validation_error(
|
||||
error,
|
||||
prefix=self.error_messages['item_invalid'],
|
||||
code='item_invalid',
|
||||
params={'nth': index + 1},
|
||||
))
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
||||
def run_validators(self, value):
|
||||
super().run_validators(value)
|
||||
errors = []
|
||||
for index, item in enumerate(value):
|
||||
try:
|
||||
self.base_field.run_validators(item)
|
||||
except ValidationError as error:
|
||||
errors.append(prefix_validation_error(
|
||||
error,
|
||||
prefix=self.error_messages['item_invalid'],
|
||||
code='item_invalid',
|
||||
params={'nth': index + 1},
|
||||
))
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
|
||||
def has_changed(self, initial, data):
|
||||
try:
|
||||
value = self.to_python(data)
|
||||
except ValidationError:
|
||||
pass
|
||||
else:
|
||||
if initial in self.empty_values and value in self.empty_values:
|
||||
return False
|
||||
return super().has_changed(initial, data)
|
||||
|
||||
|
||||
class SplitArrayWidget(forms.Widget):
|
||||
template_name = 'postgres/widgets/split_array.html'
|
||||
|
||||
def __init__(self, widget, size, **kwargs):
|
||||
self.widget = widget() if isinstance(widget, type) else widget
|
||||
self.size = size
|
||||
super().__init__(**kwargs)
|
||||
|
||||
@property
|
||||
def is_hidden(self):
|
||||
return self.widget.is_hidden
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
return [self.widget.value_from_datadict(data, files, '%s_%s' % (name, index))
|
||||
for index in range(self.size)]
|
||||
|
||||
def value_omitted_from_data(self, data, files, name):
|
||||
return all(
|
||||
self.widget.value_omitted_from_data(data, files, '%s_%s' % (name, index))
|
||||
for index in range(self.size)
|
||||
)
|
||||
|
||||
def id_for_label(self, id_):
|
||||
# See the comment for RadioSelect.id_for_label()
|
||||
if id_:
|
||||
id_ += '_0'
|
||||
return id_
|
||||
|
||||
def get_context(self, name, value, attrs=None):
|
||||
attrs = {} if attrs is None else attrs
|
||||
context = super().get_context(name, value, attrs)
|
||||
if self.is_localized:
|
||||
self.widget.is_localized = self.is_localized
|
||||
value = value or []
|
||||
context['widget']['subwidgets'] = []
|
||||
final_attrs = self.build_attrs(attrs)
|
||||
id_ = final_attrs.get('id')
|
||||
for i in range(max(len(value), self.size)):
|
||||
try:
|
||||
widget_value = value[i]
|
||||
except IndexError:
|
||||
widget_value = None
|
||||
if id_:
|
||||
final_attrs = {**final_attrs, 'id': '%s_%s' % (id_, i)}
|
||||
context['widget']['subwidgets'].append(
|
||||
self.widget.get_context(name + '_%s' % i, widget_value, final_attrs)['widget']
|
||||
)
|
||||
return context
|
||||
|
||||
@property
|
||||
def media(self):
|
||||
return self.widget.media
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
obj = super().__deepcopy__(memo)
|
||||
obj.widget = copy.deepcopy(self.widget)
|
||||
return obj
|
||||
|
||||
@property
|
||||
def needs_multipart_form(self):
|
||||
return self.widget.needs_multipart_form
|
||||
|
||||
|
||||
class SplitArrayField(forms.Field):
|
||||
default_error_messages = {
|
||||
'item_invalid': _('Item %(nth)s in the array did not validate:'),
|
||||
}
|
||||
|
||||
def __init__(self, base_field, size, *, remove_trailing_nulls=False, **kwargs):
|
||||
self.base_field = base_field
|
||||
self.size = size
|
||||
self.remove_trailing_nulls = remove_trailing_nulls
|
||||
widget = SplitArrayWidget(widget=base_field.widget, size=size)
|
||||
kwargs.setdefault('widget', widget)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def _remove_trailing_nulls(self, values):
|
||||
index = None
|
||||
if self.remove_trailing_nulls:
|
||||
for i, value in reversed(list(enumerate(values))):
|
||||
if value in self.base_field.empty_values:
|
||||
index = i
|
||||
else:
|
||||
break
|
||||
if index is not None:
|
||||
values = values[:index]
|
||||
return values, index
|
||||
|
||||
def to_python(self, value):
|
||||
value = super().to_python(value)
|
||||
return [self.base_field.to_python(item) for item in value]
|
||||
|
||||
def clean(self, value):
|
||||
cleaned_data = []
|
||||
errors = []
|
||||
if not any(value) and self.required:
|
||||
raise ValidationError(self.error_messages['required'])
|
||||
max_size = max(self.size, len(value))
|
||||
for index in range(max_size):
|
||||
item = value[index]
|
||||
try:
|
||||
cleaned_data.append(self.base_field.clean(item))
|
||||
except ValidationError as error:
|
||||
errors.append(prefix_validation_error(
|
||||
error,
|
||||
self.error_messages['item_invalid'],
|
||||
code='item_invalid',
|
||||
params={'nth': index + 1},
|
||||
))
|
||||
cleaned_data.append(None)
|
||||
else:
|
||||
errors.append(None)
|
||||
cleaned_data, null_index = self._remove_trailing_nulls(cleaned_data)
|
||||
if null_index is not None:
|
||||
errors = errors[:null_index]
|
||||
errors = list(filter(None, errors))
|
||||
if errors:
|
||||
raise ValidationError(list(chain.from_iterable(errors)))
|
||||
return cleaned_data
|
||||
|
||||
def has_changed(self, initial, data):
|
||||
try:
|
||||
data = self.to_python(data)
|
||||
except ValidationError:
|
||||
pass
|
||||
else:
|
||||
data, _ = self._remove_trailing_nulls(data)
|
||||
if initial in self.empty_values and data in self.empty_values:
|
||||
return False
|
||||
return super().has_changed(initial, data)
|
@@ -0,0 +1,58 @@
|
||||
import json
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
__all__ = ['HStoreField']
|
||||
|
||||
|
||||
class HStoreField(forms.CharField):
|
||||
"""
|
||||
A field for HStore data which accepts dictionary JSON input.
|
||||
"""
|
||||
widget = forms.Textarea
|
||||
default_error_messages = {
|
||||
'invalid_json': _('Could not load JSON data.'),
|
||||
'invalid_format': _('Input must be a JSON dictionary.'),
|
||||
}
|
||||
|
||||
def prepare_value(self, value):
|
||||
if isinstance(value, dict):
|
||||
return json.dumps(value)
|
||||
return value
|
||||
|
||||
def to_python(self, value):
|
||||
if not value:
|
||||
return {}
|
||||
if not isinstance(value, dict):
|
||||
try:
|
||||
value = json.loads(value)
|
||||
except json.JSONDecodeError:
|
||||
raise ValidationError(
|
||||
self.error_messages['invalid_json'],
|
||||
code='invalid_json',
|
||||
)
|
||||
|
||||
if not isinstance(value, dict):
|
||||
raise ValidationError(
|
||||
self.error_messages['invalid_format'],
|
||||
code='invalid_format',
|
||||
)
|
||||
|
||||
# Cast everything to strings for ease.
|
||||
for key, val in value.items():
|
||||
if val is not None:
|
||||
val = str(val)
|
||||
value[key] = val
|
||||
return value
|
||||
|
||||
def has_changed(self, initial, data):
|
||||
"""
|
||||
Return True if data differs from initial.
|
||||
"""
|
||||
# For purposes of seeing whether something has changed, None is
|
||||
# the same as an empty dict, if the data or initial value we get
|
||||
# is None, replace it w/ {}.
|
||||
initial_value = self.to_python(initial)
|
||||
return super().has_changed(initial_value, data)
|
102
venv/Lib/site-packages/django/contrib/postgres/forms/ranges.py
Normal file
102
venv/Lib/site-packages/django/contrib/postgres/forms/ranges.py
Normal file
@@ -0,0 +1,102 @@
|
||||
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.translation import gettext_lazy as _
|
||||
|
||||
__all__ = [
|
||||
'BaseRangeField', 'IntegerRangeField', 'DecimalRangeField',
|
||||
'DateTimeRangeField', 'DateRangeField', '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 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
|
Reference in New Issue
Block a user