Implementation of basic conversion between Django forms and ExtJS forms.
[philo.git] / contrib / gilbert / plugins.py
1 from inspect import isclass, getargspec
2 from functools import wraps
3 from django.utils.encoding import force_unicode
4 from django.forms.widgets import Widget, Input, HiddenInput, FileInput, DateInput, TimeInput, Textarea, CheckboxInput, Select, SelectMultiple
5 from django.forms.fields import FileField
6 from django.forms.forms import BaseForm
7
8
9 def _render_ext(self, name, value):
10         ext_spec = {'name': name}
11         if value is not None:
12                 ext_spec['value'] = value
13         if isinstance(self, Input):
14                 if isinstance(self, HiddenInput):
15                         ext_spec['xtype'] = 'hidden'
16                 elif isinstance(self, FileInput):
17                         ext_spec['xtype'] = 'fileuploadfield'
18                 elif isinstance(self, DateInput):
19                         ext_spec['xtype'] = 'datefield'
20                 elif isinstance(self, TimeInput):
21                         ext_spec['xtype'] = 'timefield'
22                 else:
23                         ext_spec['xtype'] = 'textfield'
24                         ext_spec['inputType'] = self.input_type
25         elif isinstance(self, Textarea):
26                 ext_spec['xtype'] = 'textarea'
27         elif isinstance(self, CheckboxInput):
28                 ext_spec['xtype'] = 'checkbox'
29         elif isinstance(self, Select):
30                 ext_spec['xtype'] = 'combo'
31                 ext_spec['store'] = self.choices
32                 ext_spec['typeAhead'] = True
33                 if isinstance(self, SelectMultiple):
34                         pass
35         if ext_spec:
36                 return ext_spec
37         return None
38
39
40 Widget.render_ext = _render_ext
41
42
43 def _as_ext(self):
44         ext_spec = {}
45         
46         fields = []
47         for bf in self:
48                 if bf.label:
49                         label = force_unicode(bf.label)
50                 else:
51                         label = ''
52                 
53                 if bf.field.show_hidden_initial:
54                         only_initial = True
55                 else:
56                         only_initial = False
57                 
58                 widget = bf.field.widget
59                 
60                 if not self.is_bound:
61                         data = self.initial.get(bf.name, bf.field.initial)
62                         if callable(data):
63                                 data = data()
64                 else:
65                         if isinstance(bf.field, FileField) and bf.data is None:
66                                 data = self.initial.get(bf.name, bf.field.initial)
67                         else:
68                                 data = bf.data
69                 if not only_initial:
70                         name = bf.html_name
71                 else:
72                         name = bf.html_initial_name
73                 
74                 rendered = widget.render_ext(name, data)
75                 if rendered is not None:
76                         rendered['fieldLabel'] = label
77                         fields.append(rendered)
78         ext_spec['items'] = fields
79         ext_spec['labelSeparator'] = self.label_suffix
80         return ext_spec
81
82
83 BaseForm.as_ext = _as_ext
84
85
86 def is_gilbert_method(function):
87         return getattr(function, 'gilbert_method', False)
88
89
90 def gilbert_method(function=None, name=None, argc=None, form_handler=False, restricted=True):
91         def setter(function):
92                 setattr(function, 'gilbert_method', True)
93                 setattr(function, 'name', name or function.__name__)
94                 setattr(function, 'form_handler', form_handler)
95                 setattr(function, 'restricted', restricted)
96                 new_argc = argc
97                 if new_argc is None:
98                         args = getargspec(function)[0]
99                         new_argc = len(args)
100                         if new_argc > 0:
101                                 if args[0] == 'self':
102                                         args = args[1:]
103                                         new_argc = new_argc - 1
104                                 if new_argc > 0:
105                                         if args[0] == 'request':
106                                                 args = args[1:]
107                                                 new_argc = new_argc - 1
108                 setattr(function, 'argc', new_argc)
109                 return function
110         if function is not None:
111                 return setter(function)
112         return setter
113
114
115 class GilbertPluginBase(type):
116         def __new__(cls, name, bases, attrs):
117                 if 'methods' not in attrs:
118                         methods = []
119                         for attr in attrs.values():
120                                 if is_gilbert_method(attr):
121                                         methods.append(attr.name)
122                         attrs['methods'] = methods
123                 return super(GilbertPluginBase, cls).__new__(cls, name, bases, attrs)
124
125
126 class GilbertPlugin(object):
127         __metaclass__ = GilbertPluginBase
128         
129         def __init__(self, site):
130                 self.site = site
131         
132         def get_method(self, method_name):
133                 method = getattr(self, method_name, None)
134                 if not is_gilbert_method(method):
135                         return None
136                 return method
137         
138         @property
139         def urls(self):
140                 return []
141         
142         @property
143         def js(self):
144                 return []
145         
146         @property
147         def css(self):
148                 return []
149         
150         @property
151         def fugue_icons(self):
152                 return []
153
154
155 class GilbertModelAdmin(GilbertPlugin):
156         def __init__(self, site, model):
157                 self.model = model
158                 self.name = model._meta.object_name
159                 super(GilbertModelAdmin, self).__init__(site)
160         
161         @gilbert_method
162         def all(self):
163                 return list(self.model._default_manager.all().values())
164         
165         @gilbert_method
166         def get(self, constraint):
167                 return self.model._default_manager.all().values().get(**constraint)