3
from twisted.web.woven import interfaces
4
from twisted.web.woven import widgets
5
from twisted.web.woven import model
6
from twisted.web.woven import page
7
from twisted.web.woven import controller
8
from twisted.web.woven.input import DictAggregator
10
from twisted.python import components
12
from twisted.web.microdom import lmx
13
from twisted.web.domhelpers import findElementsWithAttribute
14
from twisted.web import server
15
from twisted.web import static
16
from twisted.web import resource
17
from twisted.web import domhelpers
18
from twisted.web import microdom
21
from twisted.python import formmethod
24
class IWovenForms(components.Interface):
25
"""A mapping of form ids to form instances specific to
30
components.registerAdapter(lambda _: {}, server.Session, IWovenForms)
33
ERROR = 'A constant which indicates the most recent form which had an error.'
36
class FormPage(page.Page):
37
def getDynamicChild(self, name, request):
38
if name.startswith('woven_form_post-'):
39
forms = request.getSession(IWovenForms)
41
formId = name.split('-')[1]
44
print "we just posted to a form, ", form
46
self.formPosted = True
47
## We're posting a form instance
48
## Let's generate a DOM we can use
49
## to drive the input-validation process
50
d = microdom.parseString('<html/>')
51
content = d.childNodes[0]
52
## This will only show if we don't get redirected
53
lmx(content).h3().text("Post success!")
54
## Use the templateNode from the form
55
## to drive input validation
56
content.appendChild(form.templateNode)
57
## Tell ourself to find the dom we just created
58
self.lookupTemplate = lambda request: d
63
class FormWidget(widgets.Widget):
67
def generate(self, request, node):
68
forms = request.getSession(IWovenForms)
69
error = forms.get(ERROR)
70
if error is not None and forms[error].submodel == self.submodel:
72
## We already generated the error DOM when we checked for errors
73
return forms[error].node
74
return widgets.Widget.generate(self, request, node)
76
def setUp(self, request, node, data):
77
forms = request.getSession(IWovenForms)
78
forms[self.submodel] = self
79
self.setAttribute('action', 'woven_form_post-%s' % self.submodel)
81
body = self.getPattern('formBody', None)
84
self.appendChild(body)
86
body = request.d.createElement('table')
87
self.appendChild(body)
88
for arg in data.getArgs():
90
new = self.getPattern(name, None)
92
new = self.getPattern('formItem', None)
94
new = request.d.createElement('tr')
95
## Check to see which model we should use; the form
96
## default, or the model on the model stack directly
97
## above the formmethod... kinda hacky
98
new.setAttribute('model', name)
100
formSubmit = self.getPattern('formSubmit', None)
101
if formSubmit is not None:
102
body.appendChild(formSubmit)
106
row.td().input(type='submit', style='display: table-cell', align="right")
110
class FieldWidget(widgets.Widget):
112
def setError(self, request, error):
115
def getValue(self, request, data):
116
filled = self.model.parent.parent.getSubmodel(request, data.name)
117
if filled is not None:
118
return filled.getData(request)
119
if hasattr(data, 'value'):
123
def setUp(self, request, node, data):
125
existing = self.getPattern('fieldLabel', None, clone=False)
127
name = data.shortDesc
131
existing.childNodes = []
132
lmx(existing).text(name)
135
existing = findElementsWithAttribute(node, 'name', data.name)
137
existing = self.getPattern('fieldInput', None, clone=False)
138
if existing is not None:
139
existing = [existing]
141
viewName = data.__class__.__name__.lower()
144
existing[0].setAttribute('view', viewName)
145
existing[0].setAttribute('name', str(data.name))
146
existing[0].setAttribute('value', str(self.getValue(request, data)))
148
l.td().input(view=viewName)
150
desc = self.getPattern('fieldDescription', None, clone=False)
156
desc.text(data.longDesc)
158
err = self.getPattern('fieldError', None, clone=False)
160
err = l.td(style="color: red")
164
err.text("ERROR: "+self.error)
166
def wvupdate_input(self, request, widget, data):
167
widget.setAttribute('type', data.__class__.__name__.lower())
168
widget.setAttribute('name', data.name)
169
widget.setAttribute('value', str(self.getValue(request, data)))
171
wvupdate_password = wvupdate_input
172
wvupdate_hidden = wvupdate_input
174
def wvupdate_string(self, request, widget, data):
175
widget.setAttribute('name', data.name)
176
widget.setAttribute('value', str(self.getValue(request, data)))
178
wvupdate_integer = wvupdate_string
179
wvupdate_float = wvupdate_string
181
def wvupdate_text(self, request, widget, data):
182
widget.tagName = 'textarea'
183
widget.setAttribute('name', data.name)
184
lmx(widget).text(str(self.getValue(request, data)))
186
def wvupdate_choice(self, request, widget, data):
187
widget.tagName = 'select'
188
widget.setAttribute('name', data.name)
190
for i in range(len(data.choices)):
191
choice = data.choices[i]
192
if str(i) == str(self.getValue(request, data)):
193
l.option(value=str(i), selected='selected').text(choice)
195
l.option(value=str(i)).text(choice)
198
class FormModel(model.Model):
199
def submodelCheck(self, request, name):
200
for arg in self.original.getArgs():
204
def submodelFactory(self, request, name):
205
for arg in self.original.getArgs():
210
class FieldModel(model.Model):
214
class FormController(DictAggregator):
215
def __init__(self, *args, **kwargs):
216
DictAggregator.__init__(self, *args, **kwargs)
217
if self._commit is None:
218
self._commit = self.success
219
self._errback = self.error
221
def error(self, request, *args, **kwargs):
222
forms = request.getSession(IWovenForms)
223
formId = self.view.submodel
224
forms[formId] = self.view
225
forms[ERROR] = formId
226
from twisted.protocols import http
227
request.setResponseCode(http.SEE_OTHER)
228
request.setHeader("location", "./")
230
def success(self, *args, **kwargs):
231
print "CONTROLLER COMMIT", args, kwargs
232
self.model.original.call(**kwargs)
235
class FieldController(controller.Controller):
236
def handle(self, request):
237
filled = self.model.original
238
data = request.args.get(filled.name, [None])[0]
244
except (formmethod.InputError, formmethod.FormException), e:
246
self.view.setError(request, str(e))
247
self._parent.aggregateInvalid(request, self, data)
251
self._parent.aggregateValid(request, self, data)
253
def commit(self, *args, **kwargs):
257
components.registerAdapter(FormModel, formmethod.FormMethod, interfaces.IModel)
258
components.registerAdapter(FieldModel, formmethod.Argument, interfaces.IModel)
260
components.registerAdapter(FormWidget, FormModel, interfaces.IView)
261
components.registerAdapter(FormController, FormModel, interfaces.IController)
263
components.registerAdapter(FieldWidget, FieldModel, interfaces.IView)
264
components.registerAdapter(FieldController, FieldModel, interfaces.IController)