~certify-web-dev/twisted/certify-trunk

« back to all changes in this revision

Viewing changes to sandbox/dp/webform.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2004-06-21 22:01:11 UTC
  • mto: (2.2.3 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20040621220111-vkf909euqnyrp3nr
Tags: upstream-1.3.0
ImportĀ upstreamĀ versionĀ 1.3.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
 
 
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
 
9
 
 
10
from twisted.python import components
 
11
 
 
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
 
19
 
 
20
 
 
21
from twisted.python import formmethod
 
22
 
 
23
 
 
24
class IWovenForms(components.Interface):
 
25
    """A mapping of form ids to form instances specific to
 
26
    this session.
 
27
    """
 
28
 
 
29
 
 
30
components.registerAdapter(lambda _: {}, server.Session, IWovenForms)
 
31
 
 
32
 
 
33
ERROR = 'A constant which indicates the most recent form which had an error.'
 
34
 
 
35
 
 
36
class FormPage(page.Page):
 
37
    def getDynamicChild(self, name, request):
 
38
        if name.startswith('woven_form_post-'):
 
39
            forms = request.getSession(IWovenForms)
 
40
            print "FORMS", forms
 
41
            formId = name.split('-')[1]
 
42
            form = forms[formId]
 
43
            del forms[formId]
 
44
            print "we just posted to a form, ", form
 
45
            print request.args
 
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
 
59
            self.addSlash = 0
 
60
            return self
 
61
 
 
62
 
 
63
class FormWidget(widgets.Widget):
 
64
    formClass = None
 
65
    tagName = 'form'
 
66
    clearNode = 1
 
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:
 
71
            del forms[ERROR]
 
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)
 
75
 
 
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)
 
80
 
 
81
        body = self.getPattern('formBody', None)
 
82
        if body is not None:
 
83
            body.childNodes = []
 
84
            self.appendChild(body)
 
85
        else:
 
86
            body = request.d.createElement('table')
 
87
            self.appendChild(body)
 
88
        for arg in data.getArgs():
 
89
            name = arg.name
 
90
            new = self.getPattern(name, None)
 
91
            if new is None:
 
92
                new = self.getPattern('formItem', None)
 
93
            if new is 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)
 
99
            body.appendChild(new)
 
100
        formSubmit = self.getPattern('formSubmit', None)
 
101
        if formSubmit is not None:
 
102
            body.appendChild(formSubmit)
 
103
        else:
 
104
            row = lmx(body).tr()
 
105
            row.td()
 
106
            row.td().input(type='submit', style='display: table-cell', align="right")
 
107
            row.td()
 
108
 
 
109
 
 
110
class FieldWidget(widgets.Widget):
 
111
    error = None
 
112
    def setError(self, request, error):
 
113
        self.error = error
 
114
 
 
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'):
 
120
            return data.value
 
121
        return data.default
 
122
 
 
123
    def setUp(self, request, node, data):
 
124
        l = lmx(self)
 
125
        existing = self.getPattern('fieldLabel', None, clone=False)
 
126
        if data.shortDesc:
 
127
            name = data.shortDesc
 
128
        else:
 
129
            name=data.name
 
130
        if existing:
 
131
            existing.childNodes = []
 
132
            lmx(existing).text(name)
 
133
        else:
 
134
            l.td().text(name)
 
135
        existing = findElementsWithAttribute(node, 'name', data.name)
 
136
        if not existing:
 
137
            existing = self.getPattern('fieldInput', None, clone=False)
 
138
            if existing is not None:
 
139
                existing = [existing]
 
140
        
 
141
        viewName = data.__class__.__name__.lower()
 
142
        
 
143
        if existing:
 
144
            existing[0].setAttribute('view', viewName)
 
145
            existing[0].setAttribute('name', str(data.name))
 
146
            existing[0].setAttribute('value', str(self.getValue(request, data)))
 
147
        else:
 
148
            l.td().input(view=viewName)
 
149
        
 
150
        desc = self.getPattern('fieldDescription', None, clone=False)
 
151
        if desc is None:
 
152
            desc = l.td()
 
153
        else:
 
154
            desc.childNodes = []
 
155
            desc = lmx(desc)
 
156
        desc.text(data.longDesc)
 
157
 
 
158
        err = self.getPattern('fieldError', None, clone=False)
 
159
        if err is None:
 
160
            err = l.td(style="color: red")
 
161
        else:
 
162
            err = lmx(err)
 
163
        if self.error:
 
164
            err.text("ERROR: "+self.error)
 
165
 
 
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)))
 
170
 
 
171
    wvupdate_password = wvupdate_input
 
172
    wvupdate_hidden = wvupdate_input
 
173
 
 
174
    def wvupdate_string(self, request, widget, data):
 
175
        widget.setAttribute('name', data.name)
 
176
        widget.setAttribute('value', str(self.getValue(request, data)))
 
177
 
 
178
    wvupdate_integer = wvupdate_string
 
179
    wvupdate_float = wvupdate_string
 
180
 
 
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)))
 
185
 
 
186
    def wvupdate_choice(self, request, widget, data):
 
187
        widget.tagName = 'select'
 
188
        widget.setAttribute('name', data.name)
 
189
        l = lmx(widget)
 
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)
 
194
            else:
 
195
                l.option(value=str(i)).text(choice)
 
196
 
 
197
 
 
198
class FormModel(model.Model):
 
199
    def submodelCheck(self, request, name):
 
200
        for arg in self.original.getArgs():
 
201
            if arg.name == name:
 
202
                return True
 
203
 
 
204
    def submodelFactory(self, request, name):
 
205
        for arg in self.original.getArgs():
 
206
            if arg.name == name:
 
207
                return arg
 
208
 
 
209
 
 
210
class FieldModel(model.Model):
 
211
    pass
 
212
 
 
213
 
 
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
 
220
 
 
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", "./")
 
229
 
 
230
    def success(self, *args, **kwargs):
 
231
        print "CONTROLLER COMMIT", args, kwargs
 
232
        self.model.original.call(**kwargs)
 
233
 
 
234
 
 
235
class FieldController(controller.Controller):
 
236
    def handle(self, request):
 
237
        filled = self.model.original
 
238
        data = request.args.get(filled.name, [None])[0]
 
239
        if data is None:
 
240
            return
 
241
        
 
242
        try:
 
243
            filled.coerce(data)
 
244
        except (formmethod.InputError, formmethod.FormException), e:
 
245
            print "ERRO!",e
 
246
            self.view.setError(request, str(e))
 
247
            self._parent.aggregateInvalid(request, self, data)
 
248
            return
 
249
 
 
250
        filled.value = data
 
251
        self._parent.aggregateValid(request, self, data)
 
252
 
 
253
    def commit(self, *args, **kwargs):
 
254
        print "FIELD COMMIT"
 
255
 
 
256
 
 
257
components.registerAdapter(FormModel, formmethod.FormMethod, interfaces.IModel)
 
258
components.registerAdapter(FieldModel, formmethod.Argument, interfaces.IModel)
 
259
 
 
260
components.registerAdapter(FormWidget, FormModel, interfaces.IView)
 
261
components.registerAdapter(FormController, FormModel, interfaces.IController)
 
262
 
 
263
components.registerAdapter(FieldWidget, FieldModel, interfaces.IView)
 
264
components.registerAdapter(FieldController, FieldModel, interfaces.IController)
 
265