2 from django.forms.widgets import Widget, TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, Textarea, DateInput, DateTimeInput, TimeInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, RadioSelect, CheckboxSelectMultiple, MultiWidget, SplitHiddenDateTimeWidget
3 from django.forms.forms import BaseForm, BoundField
4 from django.forms.fields import FileField
5 from django.forms.models import ModelForm, ModelChoiceField, ModelMultipleChoiceField
6 from django.db.models import ForeignKey, ManyToManyField, Q
7 from django.utils.encoding import force_unicode
8 from philo.utils import ContentTypeLimiter
9 from philo.hacks import Category
12 # The "categories" in this module are listed in reverse order, because I wasn't able to ensure that they'd all take effect otherwise...
15 #still to do: SplitHiddenDateTimeWidget
18 class MultiWidget(MultiWidget):
19 __metaclass__ = Category
21 def render_extdirect(self, name, data):
22 if not isinstance(data, list):
23 data = self.decompress(data)
26 for i, widget in enumerate(self.widgets):
31 specs.extend(widget.render_extdirect(name + '_%s' % i, widget_data))
35 #still to do: RadioSelect, CheckboxSelectMultiple
38 class SelectMultiple(SelectMultiple):
39 __metaclass__ = Category
40 extdirect_xtype = 'superboxselect'
42 def render_extdirect(self, name, data):
44 store = [choice for choice in self.choices if choice[0]]
51 'xtype': self.extdirect_xtype,
52 'forceFormValue': False
59 class NullBooleanSelect(NullBooleanSelect):
60 __metaclass__ = Category
62 def render_extdirect(self, name, data):
64 data = {True: u'2', False: u'3', u'2': u'2', u'3': u'3'}[data]
67 return super(NullBooleanSelect, self).render_extdirect(name, data)
71 __metaclass__ = Category
72 extdirect_xtype = 'combo'
74 def render_extdirect(self, name, data):
76 store = [choice for choice in self.choices if choice[0]]
83 'xtype': self.extdirect_xtype,
86 'disableKeyFilter': True,
87 'forceSelection': True,
88 'triggerAction': 'all',
95 class CheckboxInput(CheckboxInput):
96 __metaclass__ = Category
97 extdirect_xtype = 'checkbox'
99 def render_extdirect(self, name, data):
101 specs = super(CheckboxInput, self).render_extdirect(name, data)
102 specs[0]['checked'] = data
106 class DateTimeInput(DateTimeInput):
107 __metaclass__ = Category
108 extdirect_xtype = 'gilbertdatetimefield'
111 class TimeInput(TimeInput):
112 __metaclass__ = Category
113 extdirect_xtype = 'timefield'
116 class DateInput(DateInput):
117 __metaclass__ = Category
118 extdirect_xtype = 'datefield'
121 class Textarea(Textarea):
122 __metaclass__ = Category
123 extdirect_xtype = 'textarea'
126 class FileInput(FileInput):
127 __metaclass__ = Category
128 extdirect_xtype = 'fileuploadfield'
130 def render_extdirect(self, name, data):
132 data = os.path.split(data.name)[1]
133 return super(FileInput, self).render_extdirect(name, data)
136 class MultipleHiddenInput(MultipleHiddenInput):
137 __metaclass__ = Category
138 extdirect_xtype = 'hidden'
140 def render_extdirect(self, name, data):
143 return [specs.extend(super(MultipleHiddenInput, self).render_extdirect(name, data)) for datum in data]
146 class HiddenInput(HiddenInput):
147 __metaclass__ = Category
148 extdirect_xtype = 'hidden'
151 class PasswordInput(PasswordInput):
152 __metaclass__ = Category
153 extdirect_xtype = 'textfield'
155 def render_extdirect(self, name, data):
156 specs = super(PasswordInput, self).render_extdirect(name, data)
157 specs[0]['inputType'] = self.input_type
161 class TextInput(TextInput):
162 __metaclass__ = Category
163 extdirect_xtype = 'textfield'
166 class Widget(Widget):
167 __metaclass__ = Category
168 extdirect_xtype = None
170 def render_extdirect(self, name, data):
171 if not self.extdirect_xtype:
172 raise NotImplementedError
176 'xtype': self.extdirect_xtype
178 if not spec['value']:
183 class BoundField(BoundField):
184 __metaclass__ = Category
186 def as_hidden_extdirect(self, only_initial=False):
187 return self.as_widget_extdirect(self.field.hidden_widget(), only_initial)
189 def as_widget_extdirect(self, widget=None, only_initial=False):
191 widget = self.field.widget
192 standard_widget = True
194 standard_widget = False
196 if not self.form.is_bound:
197 data = self.form.initial.get(self.name, self.field.initial)
201 if isinstance(self.field, FileField) and self.data is None:
202 data = self.form.initial.get(self.name, self.field.initial)
205 data = self.field.prepare_value(data)
208 name = self.html_name
210 name = self.html_initial_name
212 specs = widget.render_extdirect(name, data)
214 if standard_widget and isinstance(self.field, ModelChoiceField):
215 limit_choices_to = None
217 if isinstance(self.form, ModelForm):
218 model = self.form._meta.model
219 model_fields = model._meta.fields + model._meta.many_to_many
221 for model_field in model_fields:
222 if model_field.name == self.name and (isinstance(model_field, ForeignKey) or isinstance(model_field, ManyToManyField)):
223 limit_choices_to = model_field.rel.limit_choices_to
224 if limit_choices_to is None:
225 limit_choices_to = {}
226 elif isinstance(limit_choices_to, ContentTypeLimiter):
227 limit_choices_to = limit_choices_to.q_object()
228 elif not isinstance(limit_choices_to, dict):
229 limit_choices_to = None # can't support other objects with add_to_query methods
232 if limit_choices_to is not None:
233 specs[0]['model_filters'] = limit_choices_to
235 specs[0]['model_filters'] = {
236 'pk__in': self.field.queryset.values_list('pk', flat=True)
239 specs[0]['model_app_label'] = self.field.queryset.model._meta.app_label
240 specs[0]['model_name'] = self.field.queryset.model._meta.object_name
242 if isinstance(self.field, ModelMultipleChoiceField):
243 specs[0]['xtype'] = 'gilbertmodelmultiplechoicefield'
245 specs[0]['xtype'] = 'gilbertmodelchoicefield'
246 specs[0]['backup_store'] = specs[0]['store']
247 del specs[0]['store']
251 def as_extdirect(self):
252 if self.field.show_hidden_initial:
253 return self.as_widget_extdirect() + self.as_hidden_extdirect(only_initial=True)
254 return self.as_widget_extdirect()
257 class BaseForm(BaseForm):
258 __metaclass__ = Category
260 def as_extdirect(self):
263 for bound_field in self:
264 if bound_field.label:
265 label = bound_field.label
269 if bound_field.field.help_text:
270 help_text = bound_field.field.help_text
274 specs = bound_field.as_extdirect()
281 'xtype': 'compositefield',
286 specs[0]['fieldLabel'] = label
288 specs[0]['help_text'] = help_text
292 if isinstance(self, ModelForm):
293 pk = self.instance.pk
303 'labelSeparator': self.label_suffix,
304 'fileUpload': self.is_multipart()