neue Verzeichnissstruktur

This commit is contained in:
Christian Berg
2014-11-26 13:13:07 +01:00
parent daa35f5913
commit f34281089d
3372 changed files with 168 additions and 2544 deletions

23
utils/html5/__init__.py Normal file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/python
from . import base
registry = base.LookupRegistry()
def url_autodiscover():
import copy
from django.conf import settings
from django.utils.importlib import import_module
from django.utils.module_loading import module_has_submodule
for app in settings.INSTALLED_APPS:
mod = import_module(app)
# Attempt to import the app's lookups module.
try:
before_import_registry = copy.copy(registry._registry)
import_module('%s.lookups' % app)
except:
registry._registry = before_import_registry
if module_has_submodule(mod, 'lookups'):
raise

135
utils/html5/base.py Normal file
View File

@@ -0,0 +1,135 @@
import re
from django.core.urlresolvers import reverse
from django.core.serializers.json import DjangoJSONEncoder
from django.http import HttpResponse
from django.utils.encoding import smart_unicode, force_unicode
try:
import json
except ImportError:
from django.utils import simplejson as json
class LookupBase(object):
@classmethod
def name(cls):
app_name = cls.__module__.split('.')[-2].lower()
class_name = cls.__name__.lower()
name = u'%s-%s' % (app_name, class_name)
return name
@classmethod
def url(cls):
return reverse('autocomplete-lookup', args=[cls.name()])
def get_query(self, request, term):
return []
def get_item_label(self, item):
return smart_unicode(item)
def get_item_id(self, item):
return smart_unicode(item)
def get_item_value(self, item):
return smart_unicode(item)
def get_item(self, value):
return value
def create_item(self, value):
raise NotImplemented()
def format_item(self, item):
return {
'id': self.get_item_id(item),
'value': self.get_item_value(item),
'label': self.get_item_label(item)
}
def results(self, request):
term = request.GET.get('term', '')
raw_data = self.get_query(request, term)
data = []
for item in raw_data:
data.append(self.format_item(item))
content = json.dumps(data, cls=DjangoJSONEncoder, ensure_ascii=False)
return HttpResponse(content, content_type='application/json')
class LookupAlreadyRegistered(Exception):
pass
class LookupNotRegistered(Exception):
pass
class LookupInvalid(Exception):
pass
class LookupRegistry(object):
def __init__(self):
self._registry = {}
def validate(self, lookup):
if not issubclass(lookup, LookupBase):
raise LookupInvalid(u'Registered lookups must inherit from the \
LookupBase class')
def register(self, lookup):
self.validate(lookup)
name = force_unicode(lookup.name())
if name in self._registry:
raise LookupAlreadyRegistered(u'The name %s is already registered'\
% name)
self._registry[name] = lookup
def unregister(self, lookup):
self.validate(lookup)
name = force_unicode(lookup.name())
if name not in self._registry:
raise LookupNotRegistered(u'The name %s is not registered' % name)
del self._registry[name]
def get(self, key):
return self._registry.get(key, None)
class ModelLookup(LookupBase):
model = None
filters = {}
search_field = ''
def get_query(self, request, term):
qs = self.get_queryset()
if term and self.search_field:
qs = qs.filter(**{self.search_field: term})
return qs
def get_queryset(self):
qs = self.model._default_manager.get_query_set()
if self.filters:
qs = qs.filter(**self.filters)
return qs
def get_item_id(self, item):
return item.pk
def get_item(self, value):
item = None
if value:
try:
item = self.get_queryset().filter(pk=value)[0]
except IndexError:
pass
return item
def create_item(self, value):
data = {}
if self.search_field:
field_name = re.sub(r'__\w+$', '', self.search_field)
if field_name:
data = {field_name: value}
return self.model(**data)

270
utils/html5/forms.py Normal file
View File

@@ -0,0 +1,270 @@
'''
Created on 08.05.2011
@author: christian
'''
import re
from django.conf import settings
from django.core import validators
from django.core.validators import EMPTY_VALUES
from django.forms import util, Form, ModelForm, ValidationError # @UnusedImport
import django.forms.fields
from django.utils.translation import gettext as _
from . import widgets
class Html5Mixin(object):
def widget_attrs(self, widget):
'''
Overwrites the standard Widget Attributes to add some HTML5 Stuff
:param widget: A Widget Object
'''
attrs = super(Html5Mixin, self).widget_attrs(widget)
if self.required and not isinstance(widget, widgets.CheckboxInput):
attrs['required'] = 'required'
if self.help_text:
attrs['title'] = self.help_text
attrs['placeholder'] = self.help_text
if self.accesskey:
attrs['accesskey'] = self.accesskey
return attrs
def __init__(self, *args, **kwargs):
self.accesskey = kwargs.pop('accesskey', None)
super(Html5Mixin, self).__init__(*args, **kwargs)
class AutoCompleteSelectField(Html5Mixin, django.forms.Field):
widget = widgets.AutoCompleteSelectWidget
default_error_messages = {
'invalid_choice': _(u'Select a valid choice. That choice is not one \
of the available choices.'),
}
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = lookup_class
self.allow_new = kwargs.pop('allow_new', False)
if not kwargs['widget']:
kwargs['widget'] = self.widget(lookup_class,
allow_new=self.allow_new)
super(AutoCompleteSelectField, self).__init__(*args, **kwargs)
def to_python(self, value):
if value in EMPTY_VALUES:
return None
if isinstance(value, list):
# Input comes from an AutoComplete widget. It's two
# components: text and id
if len(value) != 2:
raise django.forms.ValidationError(
self.error_messages['invalid_choice'])
lookup = self.lookup_class()
if value[1] in EMPTY_VALUES:
if not self.allow_new:
if value[0]:
raise django.forms.ValidationError(
self.error_messages['invalid_choice'])
else:
return None
value = lookup.create_item(value[0])
else:
value = lookup.get_item(value[1])
if value is None:
raise django.forms.ValidationError(
self.error_messages['invalid_choice'])
return value
class AutoComboboxSelectField(AutoCompleteSelectField):
widget = widgets.AutoComboboxSelectWidget
class AutoCompleteSelectMultipleField(Html5Mixin, django.forms.Field):
widget = widgets.AutoCompleteSelectMultipleWidget
default_error_messages = {
'invalid_choice': _(u'Select a valid choice. \
That choice is not one of the available choices.'),
}
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = lookup_class
kwargs['widget'] = self.widget(lookup_class)
self.attrs['autofocus'] = 'autofocus'
super(AutoCompleteSelectMultipleField, self).__init__(*args, **kwargs)
def to_python(self, value):
if value in EMPTY_VALUES:
return None
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 django.forms.ValidationError(
self.error_messages['invalid_choice'])
items.append(item)
return items
class AutoComboboxSelectMultipleField(AutoCompleteSelectMultipleField):
widget = widgets.AutoComboboxSelectMultipleWidget
class BooleanField(Html5Mixin, django.forms.BooleanField):
widget = widgets.CheckboxInput
class CharField(Html5Mixin, django.forms.CharField):
pass
class DateField(Html5Mixin, django.forms.fields.DateField):
widget = widgets.DateInput
class DateTimeField(Html5Mixin, django.forms.fields.DateTimeField):
widget = widgets.DateTimeInput
class EmailField(Html5Mixin, django.forms.fields.EmailField):
widget = widgets.EmailInput
class FileField(Html5Mixin, django.forms.fields.FileField):
widget = widgets.NumberInput
pass
class FloatField(Html5Mixin, django.forms.fields.FloatField):
pass
class HiddenInput(Html5Mixin, django.forms.HiddenInput):
pass
class IntegerField(Html5Mixin, django.forms.fields.IntegerField):
widget = widgets.NumberInput
def widget_attrs(self, widget):
attrs = super(IntegerField, self).widget_attrs(widget)
if isinstance(widget, widgets.NumberInput):
if self.min_value is not None:
attrs['min'] = self.min_value
if self.max_value is not None:
attrs['max'] = self.max_value
return attrs
class ModelChoiceField(Html5Mixin, django.forms.ModelChoiceField):
pass
class PasswordInput(Html5Mixin, django.forms.PasswordInput):
pass
class PhoneField(Html5Mixin, django.forms.CharField):
widget = widgets.PhoneInput
def __init__(self, regex=None, max_length=None, min_length=None,
error_message=None, *args, **kwargs):
super(PhoneField, self).__init__(max_length, min_length,
*args, **kwargs)
self._set_regex(u'^[0-9+-/ ]+$')
def _get_regex(self):
return self._regex
def _set_regex(self, regex=u'^[0-9+-/ ]+$'):
regex = re.compile(regex, re.UNICODE)
self._regex = regex
if hasattr(self, '_regex_validator') \
and self._regex_validator in self.validators:
self.validators.remove(self._regex_validator)
self._regex_validator = validators.RegexValidator(regex=regex)
self.validators.append(self._regex_validator)
regex = property(_get_regex, _set_regex)
class ReCaptchaField(django.forms.fields.CharField):
def __init__(self, *args, **kwargs):
self.widget = widgets.ReCaptchaInput
self.required = True
super(ReCaptchaField, self).__init__(*args, **kwargs)
def _check_recaptcha(self, challenge_value, response_value, \
remote_ip={}):
'''
Submits a reCAPTCHA request for verification.
Returns RecaptchaResponse for the request
@param challenge_value: value of recaptcha_challenge_field
@param response_value: value of recaptcha_response_field
@param remoteip -- the user's ip address
'''
import urllib
import urllib2
private_key = settings.RECAPTCHA_PRIVATE_KEY
challenge_value = challenge_value.encode('utf-8')
response_value = response_value.encode('utf-8')
params = urllib.urlencode({
'privatekey': private_key,
'remoteip': remote_ip,
'challenge': challenge_value,
'response': response_value,
})
request = urllib2.Request(
url="http://www.google.com/recaptcha/api/verify",
data=params,
headers={
"Content-type": "application/x-www-form-urlencoded",
"User-agent": "reCAPTCHA Python"
}
)
httpresp = urllib2.urlopen(request)
return_values = httpresp.read().splitlines()
httpresp.close()
return_code = return_values[0]
if (return_code == "true"):
return True
else:
return False
def clean(self, values):
challenge_value = values[0]
response_value = values[1]
super(ReCaptchaField, self).clean(response_value)
if not challenge_value:
raise util.ValidationError(
_(u'The CAPTCHA challenge is missing.'))
elif not response_value:
raise util.ValidationError(
_(u'The CAPTCHA solution is missing.'))
elif self._check_recaptcha(challenge_value, response_value):
return challenge_value
else:
raise util.ValidationError(
_(u'The CAPTCHA solution was incorrect.'))
class RegexField(Html5Mixin, django.forms.RegexField):
pass
class SlugField(Html5Mixin, django.forms.SlugField):
pass
class URLField(Html5Mixin, django.forms.fields.URLField):
widget = widgets.URLInput

149
utils/html5/models.py Normal file
View File

@@ -0,0 +1,149 @@
'''
Created on 08.05.2011
@author: christian
'''
from django.db import models
from django.db.models import ForeignKey, Model, SET_NULL # @UnusedImport
from django.db.models import SET_DEFAULT, ManyToManyField # @UnusedImport
from django.utils import six
from . import forms, widgets
class BooleanField(models.BooleanField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.BooleanField}
defaults.update(kwargs)
return super(BooleanField, self).formfield(**defaults)
class CharField(models.CharField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.CharField}
defaults.update(kwargs)
return super(CharField, self).formfield(**defaults)
class DateField(models.DateField):
def formfield(self, **kwargs):
defaults = {
'form_class': forms.DateField}
defaults.update(kwargs)
return super(DateField, self).formfield(**defaults)
class DateTimeField(models.DateTimeField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.DateTimeField}
defaults.update(kwargs)
return super(DateTimeField, self).formfield(**defaults)
class EmailField(models.EmailField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.EmailField}
defaults.update(kwargs)
return super(EmailField, self).formfield(**defaults)
class FileField(models.FileField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.FileField}
defaults.update(kwargs)
return super(FileField, self).formfield(**defaults)
class ForeignKey(models.ForeignKey):
def formfield(self, **kwargs):
db = kwargs.pop('using', None)
if isinstance(self.rel.to, six.string_types):
raise ValueError("Cannot create form field for %r yet, because "
"its related model %r has not been loaded yet" %
(self.name, self.rel.to))
queryset = self.rel.to._default_manager.using(db)
queryset = queryset.complex_filter(self.rel.limit_choices_to)
defaults = {
'form_class': forms.ModelChoiceField,
'queryset': queryset,
'to_field_name': self.rel.field_name,
}
defaults.update(kwargs)
return super(ForeignKey, self).formfield(**defaults)
class ImageField(models.ImageField):
pass
class IntegerField(models.IntegerField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.IntegerField}
defaults.update(kwargs)
return super(IntegerField, self).formfield(**defaults)
class NullBooleanField(models.NullBooleanField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.BooleanField}
defaults.update(kwargs)
return super(NullBooleanField, self).formfield(**defaults)
class PositiveSmallIntegerField(models.PositiveSmallIntegerField):
def formfield(self, **kwargs):
defaults = {
'form_class': forms.IntegerField,
'min_value': 0,
'max_value': 32767
}
defaults.update(kwargs)
return super(PositiveSmallIntegerField, self).formfield(**defaults)
class PositiveIntegerField(models.IntegerField):
def formfield(self, **kwargs):
defaults = {
'form_class': forms.IntegerField,
'min_value': 0
}
defaults.update(kwargs)
return super(PositiveIntegerField, self).formfield(**defaults)
class SlugField(models.SlugField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.SlugField}
defaults.update(kwargs)
return super(SlugField, self).formfield(**defaults)
class TextField(models.TextField):
def formfield(self, **kwargs):
defaults = {
'form_class': forms.CharField,
'widget': widgets.Textarea
}
defaults.update(kwargs)
return super(TextField, self).formfield(**defaults)
class URLField(models.URLField):
def formfield(self, **kwargs):
defaults = {'form_class': forms.URLField}
defaults.update(kwargs)
return super(URLField, self).formfield(**defaults)

15
utils/html5/views.py Normal file
View File

@@ -0,0 +1,15 @@
'''
Created on 05.08.2011
@author: christian
'''
from django.http import Http404
from . import registry
def get_lookup(request, lookup_name):
lookup_cls = registry.get(lookup_name)
if lookup_cls is None:
raise Http404(u'Lookup %s not found' % lookup_name)
lookup = lookup_cls()
return lookup.results(request)

318
utils/html5/widgets.py Normal file
View File

@@ -0,0 +1,318 @@
'''
Created on 08.05.2011
@author: christian
'''
from django.conf import settings
from django.forms import widgets
from django.forms.util import flatatt
from django.utils import formats
from django.utils.encoding import force_unicode, force_text
from django.utils.html import conditional_escape
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
class AutoCompleteWidget(widgets.TextInput):
def __init__(self, lookup_class, attrs=None, *args, **kwargs):
self.lookup_class = lookup_class
self.allow_new = kwargs.pop('allow_new', False)
self.qs = {}
super(AutoCompleteWidget, self).__init__(*args, **kwargs)
if attrs is not None:
self.attrs = attrs.copy()
else:
self.attrs = {}
def update_query_parameters(self, qs_dict):
self.qs.update(qs_dict)
def build_attrs(self, extra_attrs=None, **kwargs):
attrs = super(AutoCompleteWidget, self).build_attrs(extra_attrs, **kwargs) # @IgnorePep8
url = self.lookup_class.url()
if self.qs:
url = '%s?%s' % (url, urlencode(self.qs))
attrs[u'data-selectable-url'] = url
attrs[u'data-selectable-type'] = 'text'
attrs[u'data-selectable-allow-new'] = str(self.allow_new).lower()
return attrs
class AutoComboboxWidget(AutoCompleteWidget):
def build_attrs(self, extra_attrs=None, **kwargs):
attrs = super(AutoComboboxWidget, self).build_attrs(extra_attrs, **kwargs) # @IgnorePep8
attrs[u'data-selectable-type'] = 'combobox'
return attrs
class DateInput(widgets.DateInput):
input_type = 'date'
attrs = {'class': 'dateinput'}
def __init__(self, attrs=None, date_format='%Y-%m-%d'):
super(DateInput, self).__init__(attrs)
if date_format:
self.format = date_format
self.manual_format = True
else:
self.format = formats.get_format('DATE_INPUT_FORMATS')[0]
self.manual_format = False
class DateTimeInput(widgets.MultiWidget):
"""
A Widget that splits datetime input into two <input type="text"> boxes.
"""
def __init__(self, attrs=None, date_format='%Y-%m-%d', time_format='%H:%M'): # @IgnorePep8
widgets = (
DateInput(attrs=attrs, date_format=date_format),
TimeInput(attrs=attrs, time_format=time_format)
)
super(DateTimeInput, self).__init__(widgets, attrs)
def decompress(self, value):
if value:
return [value.date(), value.time()]
return [None, None]
class CheckboxInput(widgets.CheckboxInput):
input_type = 'checkbox'
is_checkbox = True
def render(self, name, value, attrs=None):
final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
title = force_text(self.attrs.get('title', ''))
try:
result = self.check_test(value)
except: # Silently catch exceptions
result = False
if result:
final_attrs['checked'] = 'checked'
if not (value is True or value is False or value is None or value == ''): # @IgnorePep8
# Only add the 'value' attribute if a value is non-empty.
final_attrs['value'] = force_unicode(value)
return mark_safe(u'<input%s /> %s' % (flatatt(final_attrs), title))
class EmailInput(widgets.TextInput):
input_type = 'email'
class NumberInput(widgets.TextInput):
input_type = 'number'
def __init__(self, attrs=None):
widgets.Input.__init__(self, attrs=attrs)
class PhoneInput(widgets.TextInput):
input_type = 'tel'
class RangeInput(widgets.TextInput):
input_type = 'range'
class ReCaptchaInput(widgets.Widget):
'''
Der HTML Code von Googles ReCaptcha als Form Widget
'''
recaptcha_challenge_name = 'recaptcha_challenge_field'
recaptcha_response_name = 'recaptcha_response_field'
def render(self, name, value, attrs=None):
javascript = u"""
<script type="text/javascript">var RecaptchaOptions = {theme :
'%(theme)s'};</script><script type="text/javascript"
src="https://www.google.com/recaptcha/api/challenge?k=%(public_key)s">
</script><noscript><iframe
src="https://www.google.com/recaptcha/api/noscript?k=%(public_key)s"
height="300" width="500" frameborder="0"></iframe><br /><textarea
name="recaptcha_challenge_field" rows="3" cols="40"></textarea><input
type="hidden" name="recaptcha_response_field" value="manual_challenge">
</noscript>"""
return mark_safe(javascript % {'public_key':
settings.RECAPTCHA_PUBLIC_KEY, 'theme': 'red'})
def value_from_datadict(self, data, files, name):
return [data.get(self.recaptcha_challenge_name, None),
data.get(self.recaptcha_response_name, None)]
class SelectableMultiWidget(widgets.MultiWidget):
def update_query_parameters(self, qs_dict):
self.widgets[0].update_query_parameters(qs_dict)
class Textarea(widgets.Widget):
def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness.
default_attrs = {'cols': '40', 'rows': '10'}
if attrs:
default_attrs.update(attrs)
super(Textarea, self).__init__(default_attrs)
def render(self, name, value, attrs=None):
value = '' if value is None else value
final_attrs = self.build_attrs(attrs, name=name)
return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
conditional_escape(force_unicode(value))))
class TextInput(widgets.TextInput):
pass
class TimeInput(widgets.TimeInput):
input_type = 'time'
def __init__(self, attrs=None, time_format='%H:%M'):
default_attrs = {'maxlength': 5, 'size': 5}
if attrs:
default_attrs.update(attrs)
super(TimeInput, self).__init__(default_attrs)
if time_format:
self.format = time_format
self.manual_format = True
else:
self.format = formats.get_format('TIME_INPUT_FORMATS')[0]
self.manual_format = False
class URLInput(widgets.Input):
input_type = 'url'
class LookupMultipleHiddenInput(widgets.MultipleHiddenInput):
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = lookup_class
super(LookupMultipleHiddenInput, self).__init__(*args, **kwargs)
def render(self, name, value, attrs=None, choices=()):
lookup = self.lookup_class()
value = [] if value is None else value
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
id_ = final_attrs.get('id', None)
inputs = []
model = getattr(self.lookup_class, 'model', None)
for i, v in enumerate(value):
item = None
if model and isinstance(v, model):
item = v
v = lookup.get_item_id(item)
input_attrs = dict(value=force_unicode(v), **final_attrs)
if id_:
# An ID attribute was given. Add a numeric index as a suffix
# so that the inputs don't all have the same ID attribute.
input_attrs['id'] = '%s_%s' % (id_, i)
if v:
item = item or lookup.get_item(v)
input_attrs['title'] = lookup.get_item_value(item)
inputs.append(u'<input%s />' % flatatt(input_attrs))
return mark_safe(u'\n'.join(inputs))
def build_attrs(self, extra_attrs=None, **kwargs):
attrs = super(LookupMultipleHiddenInput, self).build_attrs(extra_attrs, **kwargs) # @IgnorePep8
attrs[u'data-selectable-type'] = 'hidden-multiple'
return attrs
class AutoCompleteSelectMultipleWidget(SelectableMultiWidget):
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = lookup_class
widgets = [
AutoCompleteWidget(lookup_class, allow_new=False,
attrs={u'data-selectable-multiple': 'true'}),
LookupMultipleHiddenInput(lookup_class)
]
super(AutoCompleteSelectMultipleWidget, self).__init__(widgets, *args, **kwargs) # @IgnorePep8
def value_from_datadict(self, data, files, name):
return self.widgets[1].value_from_datadict(data, files, name + '_1')
def render(self, name, value, attrs=None):
if value and not hasattr(value, '__iter__'):
value = [value]
value = [u'', value]
return super(AutoCompleteSelectMultipleWidget, self).render(name, value, attrs) # @IgnorePep8
class AutoComboboxSelectMultipleWidget(SelectableMultiWidget):
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = lookup_class
widgets = [
AutoComboboxWidget(lookup_class, allow_new=False,
attrs={u'data-selectable-multiple': 'true'}),
LookupMultipleHiddenInput(lookup_class)
]
super(AutoComboboxSelectMultipleWidget, self).__init__(widgets, *args, **kwargs) # @IgnorePep8
def value_from_datadict(self, data, files, name):
return self.widgets[1].value_from_datadict(data, files, name + '_1')
def render(self, name, value, attrs=None):
if value and not hasattr(value, '__iter__'):
value = [value]
value = [u'', value]
return super(AutoComboboxSelectMultipleWidget, self).render(name, value, attrs) # @IgnorePep8
class AutoCompleteSelectWidget(SelectableMultiWidget):
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = lookup_class
self.allow_new = kwargs.pop('allow_new', False)
widget_set = [
AutoCompleteWidget(lookup_class, allow_new=self.allow_new),
widgets.HiddenInput(attrs={u'data-selectable-type': 'hidden'})
]
super(AutoCompleteSelectWidget, self).__init__(widget_set, *args, **kwargs) # @IgnorePep8
def decompress(self, value):
if value:
lookup = self.lookup_class()
model = getattr(self.lookup_class, 'model', None)
if model and isinstance(value, model):
item = value
value = lookup.get_item_id(item)
else:
item = lookup.get_item(value)
item_value = lookup.get_item_value(item)
return [item_value, value]
return [None, None]
class AutoComboboxSelectWidget(SelectableMultiWidget):
def __init__(self, lookup_class, *args, **kwargs):
self.lookup_class = lookup_class
self.allow_new = kwargs.pop('allow_new', False)
widget_set = [
AutoComboboxWidget(lookup_class, allow_new=self.allow_new),
widgets.HiddenInput(attrs={u'data-selectable-type': 'hidden'})
]
super(AutoComboboxSelectWidget, self).__init__(widget_set, *args, **kwargs) # @IgnorePep8
def decompress(self, value):
if value:
lookup = self.lookup_class()
model = getattr(self.lookup_class, 'model', None)
if model and isinstance(value, model):
item = value
value = lookup.get_item_id(item)
else:
item = lookup.get_item(value)
item_value = lookup.get_item_value(item)
return [item_value, value]
return [None, None]