summaryrefslogtreecommitdiff
path: root/ishtar_common/widgets.py
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common/widgets.py')
-rw-r--r--ishtar_common/widgets.py144
1 files changed, 102 insertions, 42 deletions
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index 42a93ddaa..4efb4c3fb 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -26,15 +26,16 @@ from django.conf import settings
from django.core.urlresolvers import reverse, NoReverseMatch
from django.db.models import fields
from django.forms import ClearableFileInput
-from django.forms.widgets import flatatt, \
- CheckboxSelectMultiple as CheckboxSelectMultipleBase
-from django.template import Context, loader
+from django.forms.utils import flatatt
+from django.forms.widgets import CheckboxSelectMultiple as \
+ CheckboxSelectMultipleBase
+from django.template import loader
from django.template.defaultfilters import slugify
from django.utils.encoding import smart_unicode
from django.utils.functional import lazy
from django.utils.html import escape
from django.utils.safestring import mark_safe
-from django.utils.simplejson import JSONEncoder
+from json import JSONEncoder
from django.utils.translation import ugettext_lazy as _
from ishtar_common import models
@@ -44,6 +45,61 @@ logger = logging.getLogger(__name__)
reverse_lazy = lazy(reverse, unicode)
+class SelectReadonly(forms.Select):
+ template_name = 'blocks/readonly_input.html'
+ option_template_name = 'blocks/readonly_input_option.html'
+
+ def __init__(self, attrs=None, choices=(), model=None, available=None):
+ super(SelectReadonly, self).__init__(attrs, choices)
+ self.available = available
+ self.model = model
+
+ def get_choices(self, value):
+ q = self.model.objects
+ if self.available:
+ q = q.filter(available=True)
+ if value:
+ q = q.filter(pk=value)
+ for i in q.all():
+ if hasattr(self.model, 'verbose_name'):
+ label = i.verbose_name
+ else:
+ label = unicode(i)
+ yield (i.pk, label)
+
+ def render(self, name, value, attrs=None, choices=()):
+ if value:
+ self.choices = list(self.get_choices(value))
+ value = self.choices[0][0]
+ return super(SelectReadonly, self).render(name, value, attrs)
+
+
+class SelectReadonlyField(forms.ChoiceField):
+ def __init__(self, choices=(), required=True, widget=None, label=None,
+ initial=None, help_text='', *args, **kwargs):
+ self.available = False
+ self.model = None
+ if 'model' in kwargs:
+ self.model = kwargs.pop('model')
+ if 'available' in kwargs:
+ self.available = kwargs.pop('available')
+ widget = SelectReadonly(model=self.model, available=self.available)
+ super(SelectReadonlyField, self).__init__(
+ choices, required, widget, label, initial, help_text, *args,
+ **kwargs)
+
+ def get_q(self):
+ q = self.model.objects
+ if self.available:
+ q = q.filter(available=True)
+ return q
+
+ def valid_value(self, value):
+ if not self.model:
+ return super(SelectReadonlyField, self).valid_value(value)
+ return bool(self.get_q().filter(pk=value).count())
+
+
class Select2Multiple(forms.SelectMultiple):
def __init__(self, attrs=None, choices=(), remote=None, model=None,
available=None):
@@ -80,8 +136,11 @@ class Select2Multiple(forms.SelectMultiple):
if self.remote in ('None', 'false'):
# test on lazy object is buggy... so we have this ugly test
self.remote = None
- if not choices and not self.remote and self.model:
- choices = self.get_choices()
+ if not choices:
+ if not self.remote and self.model:
+ choices = self.get_choices()
+ if hasattr(self, 'choices') and self.choices:
+ choices = self.choices
new_attrs = self.attrs.copy()
new_attrs.update(attrs)
attrs = new_attrs
@@ -134,8 +193,8 @@ class Select2Multiple(forms.SelectMultiple):
else:
options = "{"
options += " containerCssClass: 'full-width'}"
- html = super(Select2Multiple, self).render(name, value, attrs,
- choices)
+ self.choices = choices
+ html = super(Select2Multiple, self).render(name, value, attrs)
html += """<script type="text/javascript">
$(document).ready(function() {{
$("#id_{}").select2({});
@@ -155,8 +214,7 @@ class CheckboxSelectMultiple(CheckboxSelectMultipleBase):
value = value.split(',')
if type(value) not in (list, tuple):
value = [value]
- return super(CheckboxSelectMultiple, self).render(name, value, attrs,
- choices)
+ return super(CheckboxSelectMultiple, self).render(name, value, attrs)
class Select2MultipleField(forms.MultipleChoiceField):
@@ -191,9 +249,9 @@ class Select2MultipleField(forms.MultipleChoiceField):
class DeleteWidget(forms.CheckboxInput):
- def render(self, name, value, attrs=None):
- final_attrs = flatatt(self.build_attrs(attrs, name=name,
- value='1'))
+ def render(self, name, value, attrs=None, renderer=None):
+ final_attrs = flatatt(
+ self.build_attrs(attrs, {"name": name, "value": '1'}))
output = ['<tr class="delete"><td colspan="2">']
output.append(u"<button%s>%s</button>" % (final_attrs, _("Delete")))
output.append('</td></tr>')
@@ -206,16 +264,17 @@ class ImageFileInput(ClearableFileInput):
class SquareMeterWidget(forms.TextInput):
- def render(self, name, value, attrs=None):
+ def render(self, name, value, attrs=None, renderer=None):
if not value:
value = u""
- final_attrs = flatatt(self.build_attrs(attrs, name=name, value=value))
+ final_attrs = flatatt(
+ self.build_attrs(attrs, {"name": name, "value": value}))
dct = {'final_attrs': final_attrs,
'unit': settings.SURFACE_UNIT_LABEL,
'id': attrs['id'],
"safe_id": attrs['id'].replace('-', '_')}
t = loader.get_template('blocks/SquareMeterWidget.html')
- rendered = t.render(Context(dct))
+ rendered = t.render(dct)
return mark_safe(rendered)
AreaWidget = forms.TextInput
@@ -231,7 +290,7 @@ class JQueryDate(forms.TextInput):
self.attrs['class'] = ''
self.attrs['class'] = 'date-pickup'
- def render(self, name, value=None, attrs=None):
+ def render(self, name, value, attrs=None, renderer=None):
if value:
value = unicode(value)
# very specific...
@@ -266,25 +325,29 @@ class JQueryDate(forms.TextInput):
class JQueryAutoComplete(forms.TextInput):
- def __init__(self, source, associated_model=None, options={}, attrs={},
- new=False, url_new='', multiple=False, limit={},
- dynamic_limit=[]):
+ def __init__(self, source, associated_model=None, options=None, attrs=None,
+ new=False, url_new='', multiple=False, limit=None,
+ dynamic_limit=None):
"""
Source can be a list containing the autocomplete values or a
string containing the url used for the request.
"""
- self.options = None
- self.attrs = {}
self.source = source
self.associated_model = associated_model
- if len(options) > 0:
+
+ self.options = None
+ if options and len(options) > 0:
self.options = JSONEncoder().encode(options)
- self.attrs.update(attrs)
+ self.attrs = {}
+
+ if attrs:
+ self.attrs.update(attrs)
+
self.new = new
self.url_new = url_new
self.multiple = multiple
- self.limit = limit
- self.dynamic_limit = dynamic_limit
+ self.limit = limit or {}
+ self.dynamic_limit = dynamic_limit or []
def value_from_datadict(self, data, files, name):
if self.multiple:
@@ -313,22 +376,20 @@ class JQueryAutoComplete(forms.TextInput):
if self.options:
dct['options'] = mark_safe('%s' % self.options)
- js = ""
tpl = 'blocks/JQueryAutocomplete.js'
if self.multiple:
tpl = 'blocks/JQueryAutocompleteMultiple.js'
t = loader.get_template(tpl)
- js = t.render(Context(dct))
+ js = t.render(dct)
return js
- def render(self, name, value=None, attrs=None):
- attrs_hidden = self.build_attrs(attrs, name=name)
+ def render(self, name, value, attrs=None, renderer=None):
+ attrs_hidden = self.build_attrs(attrs, {"name": name})
attrs_select = self.build_attrs(attrs)
attrs_select['placeholder'] = _(u"Search...")
if value:
hiddens = []
selects = []
- values = value
if type(value) not in (list, tuple):
values = unicode(escape(smart_unicode(value)))
values = values.replace('[', '').replace(']', '')
@@ -428,8 +489,8 @@ class JQueryTown(forms.TextInput):
raise ValueError('source type is not valid')
return encoded_src
- def render(self, name, value=None, attrs=None):
- attrs_hidden = self.build_attrs(attrs, name=name)
+ def render(self, name, value, attrs=None, renderer=None):
+ attrs_hidden = self.build_attrs(attrs, {"name": name})
attrs_select = self.build_attrs(attrs)
attrs_select['placeholder'] = _(u"Search...")
selected = ''
@@ -487,7 +548,7 @@ class JQueryTown(forms.TextInput):
'selected_state': selected_state}
)
html = loader.get_template('blocks/JQueryAdvancedTown.html')\
- .render(Context(dct))
+ .render(dct)
return html
@@ -540,11 +601,11 @@ class JQueryPersonOrganization(forms.TextInput):
'field_id': field_id}
if self.options:
dct['options'] = mark_safe('%s' % self.options)
- js = loader.get_template(self.js_template).render(Context(dct))
+ js = loader.get_template(self.js_template).render(dct)
return js
- def render(self, name, value=None, attrs=None):
- attrs_hidden = self.build_attrs(attrs, name=name)
+ def render(self, name, value, attrs=None, renderer=None):
+ attrs_hidden = self.build_attrs(attrs, {'name': name})
attrs_select = self.build_attrs(attrs)
attrs_select['placeholder'] = _(u"Search...")
selected = ''
@@ -586,7 +647,7 @@ class JQueryPersonOrganization(forms.TextInput):
'name': name,
'js': self.render_js(name, selected),
'new': mark_safe(new)}
- html = loader.get_template(self.html_template).render(Context(dct))
+ html = loader.get_template(self.html_template).render(dct)
return html
@@ -692,11 +753,10 @@ class JQueryJqGrid(forms.RadioSelect):
extra_cols = extra_cols and ", ".join(extra_cols) or ""
return jq_col_names, extra_cols
- def render(self, name, value=None, attrs=None):
+ def render(self, name, value, attrs=None, renderer=None):
t = loader.get_template('blocks/form_flex_snippet.html')
form = self.form()
- rendered = t.render(Context({'form': form,
- 'flex': True}))
+ rendered = t.render({'form': form, 'flex': True})
dct = {}
if self.new:
model_name = self.associated_model._meta.object_name.lower()
@@ -744,5 +804,5 @@ class JQueryJqGrid(forms.RadioSelect):
'multi_cols': ",".join((u'"%d"' % col
for col in self.multiple_cols))})
t = loader.get_template('blocks/JQueryJqGrid.html')
- rendered += t.render(Context(dct))
+ rendered += t.render(dct)
return mark_safe(rendered)