mirror of
https://github.com/postgres/pgweb.git
synced 2025-08-10 00:42:06 +00:00

Sync up to the same version we have on the commitfest app, which will also be required for eventual django 1.11 support.
124 lines
4.3 KiB
Python
124 lines
4.3 KiB
Python
from __future__ import unicode_literals
|
|
|
|
from django import forms, VERSION as DJANGO_VERSION
|
|
from django.core.exceptions import ValidationError
|
|
from django.core.validators import EMPTY_VALUES
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.db.models import Model
|
|
|
|
from selectable.forms.base import import_lookup_class
|
|
from selectable.forms.widgets import AutoCompleteSelectWidget
|
|
from selectable.forms.widgets import AutoCompleteSelectMultipleWidget
|
|
|
|
__all__ = (
|
|
'AutoCompleteSelectField',
|
|
'AutoCompleteSelectMultipleField',
|
|
)
|
|
|
|
|
|
def model_vars(obj):
|
|
fields = dict(
|
|
(field.name, getattr(obj, field.name))
|
|
for field in obj._meta.fields
|
|
)
|
|
return fields
|
|
|
|
|
|
class BaseAutoCompleteField(forms.Field):
|
|
|
|
def has_changed(self, initial, data):
|
|
"Detects if the data was changed. This is added in 1.6."
|
|
if initial is None and data is None:
|
|
return False
|
|
if data and not hasattr(data, '__iter__'):
|
|
data = self.widget.decompress(data)
|
|
initial = self.to_python(initial)
|
|
data = self.to_python(data)
|
|
if hasattr(self, '_coerce'):
|
|
data = self._coerce(data)
|
|
if isinstance(data, Model) and isinstance(initial, Model):
|
|
return model_vars(data) != model_vars(initial)
|
|
else:
|
|
return data != initial
|
|
|
|
if DJANGO_VERSION < (1, 8):
|
|
def _has_changed(self, initial, data):
|
|
return self.has_changed(initial, data)
|
|
|
|
|
|
class AutoCompleteSelectField(BaseAutoCompleteField):
|
|
widget = AutoCompleteSelectWidget
|
|
|
|
default_error_messages = {
|
|
'invalid_choice': _('Select a valid choice. That choice is not one of the available choices.'),
|
|
}
|
|
|
|
def __init__(self, lookup_class, *args, **kwargs):
|
|
self.lookup_class = import_lookup_class(lookup_class)
|
|
self.allow_new = kwargs.pop('allow_new', False)
|
|
self.limit = kwargs.pop('limit', None)
|
|
widget = kwargs.get('widget', self.widget) or self.widget
|
|
if isinstance(widget, type):
|
|
kwargs['widget'] = widget(lookup_class, allow_new=self.allow_new, limit=self.limit)
|
|
super(AutoCompleteSelectField, self).__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def to_python(self, value):
|
|
if value in EMPTY_VALUES:
|
|
return None
|
|
lookup = self.lookup_class()
|
|
if isinstance(value, list):
|
|
# Input comes from an AutoComplete widget. It's two
|
|
# components: text and id
|
|
if len(value) != 2:
|
|
raise ValidationError(self.error_messages['invalid_choice'])
|
|
label, pk = value
|
|
if pk in EMPTY_VALUES:
|
|
if not self.allow_new:
|
|
if label:
|
|
raise ValidationError(self.error_messages['invalid_choice'])
|
|
else:
|
|
return None
|
|
if label in EMPTY_VALUES:
|
|
return None
|
|
value = lookup.create_item(label)
|
|
else:
|
|
value = lookup.get_item(pk)
|
|
if value is None:
|
|
raise ValidationError(self.error_messages['invalid_choice'])
|
|
else:
|
|
value = lookup.get_item(value)
|
|
if value is None:
|
|
raise ValidationError(self.error_messages['invalid_choice'])
|
|
return value
|
|
|
|
|
|
class AutoCompleteSelectMultipleField(BaseAutoCompleteField):
|
|
widget = AutoCompleteSelectMultipleWidget
|
|
|
|
default_error_messages = {
|
|
'invalid_choice': _('Select a valid choice. That choice is not one of the available choices.'),
|
|
}
|
|
|
|
def __init__(self, lookup_class, *args, **kwargs):
|
|
self.lookup_class = import_lookup_class(lookup_class)
|
|
self.limit = kwargs.pop('limit', None)
|
|
widget = kwargs.get('widget', self.widget) or self.widget
|
|
if isinstance(widget, type):
|
|
kwargs['widget'] = widget(lookup_class, limit=self.limit)
|
|
super(AutoCompleteSelectMultipleField, self).__init__(*args, **kwargs)
|
|
|
|
def to_python(self, value):
|
|
if value in EMPTY_VALUES:
|
|
return []
|
|
lookup = self.lookup_class()
|
|
items = []
|
|
for v in value:
|
|
if v not in EMPTY_VALUES:
|
|
item = lookup.get_item(v)
|
|
if item is None:
|
|
raise ValidationError(self.error_messages['invalid_choice'])
|
|
items.append(item)
|
|
return items
|