from twisted.web.woven import interfaces
from twisted.web.woven import widgets
from twisted.web.woven import model
from twisted.web.woven import page
from twisted.web.woven import controller
from twisted.web.woven.input import DictAggregator
from twisted.python import components
from twisted.web.microdom import lmx
from twisted.web.domhelpers import findElementsWithAttribute
from twisted.web import server
from twisted.web import static
from twisted.web import resource
from twisted.web import domhelpers
from twisted.web import microdom
from twisted.python import formmethod
class IWovenForms(components.Interface):
"""A mapping of form ids to form instances specific to
this session.
"""
components.registerAdapter(lambda _: {}, server.Session, IWovenForms)
ERROR = 'A constant which indicates the most recent form which had an error.'
class FormPage(page.Page):
def getDynamicChild(self, name, request):
if name.startswith('woven_form_post-'):
forms = request.getSession(IWovenForms)
print "FORMS", forms
formId = name.split('-')[1]
form = forms[formId]
del forms[formId]
print "we just posted to a form, ", form
print request.args
self.formPosted = True
d = microdom.parseString('<html/>')
content = d.childNodes[0]
lmx(content).h3().text("Post success!")
content.appendChild(form.templateNode)
self.lookupTemplate = lambda request: d
self.addSlash = 0
return self
class FormWidget(widgets.Widget):
formClass = None
tagName = 'form'
clearNode = 1
def generate(self, request, node):
forms = request.getSession(IWovenForms)
error = forms.get(ERROR)
if error is not None and forms[error].submodel == self.submodel:
del forms[ERROR]
return forms[error].node
return widgets.Widget.generate(self, request, node)
def setUp(self, request, node, data):
forms = request.getSession(IWovenForms)
forms[self.submodel] = self
self.setAttribute('action', 'woven_form_post-%s' % self.submodel)
body = self.getPattern('formBody', None)
if body is not None:
body.childNodes = []
self.appendChild(body)
else:
body = request.d.createElement('table')
self.appendChild(body)
for arg in data.getArgs():
name = arg.name
new = self.getPattern(name, None)
if new is None:
new = self.getPattern('formItem', None)
if new is None:
new = request.d.createElement('tr')
new.setAttribute('model', name)
body.appendChild(new)
formSubmit = self.getPattern('formSubmit', None)
if formSubmit is not None:
body.appendChild(formSubmit)
else:
row = lmx(body).tr()
row.td()
row.td().input(type='submit', style='display: table-cell', align="right")
row.td()
class FieldWidget(widgets.Widget):
error = None
def setError(self, request, error):
self.error = error
def getValue(self, request, data):
filled = self.model.parent.parent.getSubmodel(request, data.name)
if filled is not None:
return filled.getData(request)
if hasattr(data, 'value'):
return data.value
return data.default
def setUp(self, request, node, data):
l = lmx(self)
existing = self.getPattern('fieldLabel', None, clone=False)
if data.shortDesc:
name = data.shortDesc
else:
name=data.name
if existing:
existing.childNodes = []
lmx(existing).text(name)
else:
l.td().text(name)
existing = findElementsWithAttribute(node, 'name', data.name)
if not existing:
existing = self.getPattern('fieldInput', None, clone=False)
if existing is not None:
existing = [existing]
viewName = data.__class__.__name__.lower()
if existing:
existing[0].setAttribute('view', viewName)
existing[0].setAttribute('name', str(data.name))
existing[0].setAttribute('value', str(self.getValue(request, data)))
else:
l.td().input(view=viewName)
desc = self.getPattern('fieldDescription', None, clone=False)
if desc is None:
desc = l.td()
else:
desc.childNodes = []
desc = lmx(desc)
desc.text(data.longDesc)
err = self.getPattern('fieldError', None, clone=False)
if err is None:
err = l.td(style="color: red")
else:
err = lmx(err)
if self.error:
err.text("ERROR: "+self.error)
def wvupdate_input(self, request, widget, data):
widget.setAttribute('type', data.__class__.__name__.lower())
widget.setAttribute('name', data.name)
widget.setAttribute('value', str(self.getValue(request, data)))
wvupdate_password = wvupdate_input
wvupdate_hidden = wvupdate_input
def wvupdate_string(self, request, widget, data):
widget.setAttribute('name', data.name)
widget.setAttribute('value', str(self.getValue(request, data)))
wvupdate_integer = wvupdate_string
wvupdate_float = wvupdate_string
def wvupdate_text(self, request, widget, data):
widget.tagName = 'textarea'
widget.setAttribute('name', data.name)
lmx(widget).text(str(self.getValue(request, data)))
def wvupdate_choice(self, request, widget, data):
widget.tagName = 'select'
widget.setAttribute('name', data.name)
l = lmx(widget)
for i in range(len(data.choices)):
choice = data.choices[i]
if str(i) == str(self.getValue(request, data)):
l.option(value=str(i), selected='selected').text(choice)
else:
l.option(value=str(i)).text(choice)
class FormModel(model.Model):
def submodelCheck(self, request, name):
for arg in self.original.getArgs():
if arg.name == name:
return True
def submodelFactory(self, request, name):
for arg in self.original.getArgs():
if arg.name == name:
return arg
class FieldModel(model.Model):
pass
class FormController(DictAggregator):
def __init__(self, *args, **kwargs):
DictAggregator.__init__(self, *args, **kwargs)
if self._commit is None:
self._commit = self.success
self._errback = self.error
def error(self, request, *args, **kwargs):
forms = request.getSession(IWovenForms)
formId = self.view.submodel
forms[formId] = self.view
forms[ERROR] = formId
from twisted.protocols import http
request.setResponseCode(http.SEE_OTHER)
request.setHeader("location", "./")
def success(self, *args, **kwargs):
print "CONTROLLER COMMIT", args, kwargs
self.model.original.call(**kwargs)
class FieldController(controller.Controller):
def handle(self, request):
filled = self.model.original
data = request.args.get(filled.name, [None])[0]
if data is None:
return
try:
filled.coerce(data)
except (formmethod.InputError, formmethod.FormException), e:
print "ERRO!",e
self.view.setError(request, str(e))
self._parent.aggregateInvalid(request, self, data)
return
filled.value = data
self._parent.aggregateValid(request, self, data)
def commit(self, *args, **kwargs):
print "FIELD COMMIT"
components.registerAdapter(FormModel, formmethod.FormMethod, interfaces.IModel)
components.registerAdapter(FieldModel, formmethod.Argument, interfaces.IModel)
components.registerAdapter(FormWidget, FormModel, interfaces.IView)
components.registerAdapter(FormController, FormModel, interfaces.IController)
components.registerAdapter(FieldWidget, FieldModel, interfaces.IView)
components.registerAdapter(FieldController, FieldModel, interfaces.IController)