''' 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 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' %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""" """ 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'%s' % (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'' % 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]