| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 # -*- test-case-name: twisted.web.test.test_woven -*- |  | 
| 2 # |  | 
| 3 # WORK IN PROGRESS: HARD HAT REQUIRED |  | 
| 4 # |  | 
| 5 |  | 
| 6 from __future__ import nested_scopes |  | 
| 7 |  | 
| 8 # Twisted Imports |  | 
| 9 |  | 
| 10 from twisted.python import formmethod, failure |  | 
| 11 from twisted.python.components import registerAdapter |  | 
| 12 from twisted.web import domhelpers, resource, util |  | 
| 13 from twisted.internet import defer |  | 
| 14 |  | 
| 15 # Sibling Imports |  | 
| 16 from twisted.web.woven import model, view, controller, widgets, input, interface
     s |  | 
| 17 |  | 
| 18 from twisted.web.microdom import parseString, lmx, Element |  | 
| 19 |  | 
| 20 |  | 
| 21 #other imports |  | 
| 22 import math |  | 
| 23 |  | 
| 24 # map formmethod.Argument to functions that render them: |  | 
| 25 _renderers = {} |  | 
| 26 |  | 
| 27 def registerRenderer(argumentClass, renderer): |  | 
| 28     """Register a renderer for a given argument class. |  | 
| 29 |  | 
| 30     The renderer function should act in the same way |  | 
| 31     as the 'input_XXX' methods of C{FormFillerWidget}. |  | 
| 32     """ |  | 
| 33     assert callable(renderer) |  | 
| 34     global _renderers |  | 
| 35     _renderers[argumentClass] = renderer |  | 
| 36 |  | 
| 37 |  | 
| 38 class FormFillerWidget(widgets.Widget): |  | 
| 39 |  | 
| 40     SPANNING_TYPES = ["hidden", "submit"] |  | 
| 41 |  | 
| 42     def getValue(self, request, argument): |  | 
| 43         """Return value for form input.""" |  | 
| 44         if not self.model.alwaysDefault: |  | 
| 45             values = request.args.get(argument.name, None) |  | 
| 46             if values: |  | 
| 47                 try: |  | 
| 48                     return argument.coerce(values[0]) |  | 
| 49                 except formmethod.InputError: |  | 
| 50                     return values[0] |  | 
| 51         return argument.default |  | 
| 52 |  | 
| 53     def getValues(self, request, argument): |  | 
| 54         """Return values for form input.""" |  | 
| 55         if not self.model.alwaysDefault: |  | 
| 56             values = request.args.get(argument.name, None) |  | 
| 57             if values: |  | 
| 58                 try: |  | 
| 59                     return argument.coerce(values) |  | 
| 60                 except formmethod.InputError: |  | 
| 61                     return values |  | 
| 62         return argument.default |  | 
| 63 |  | 
| 64     def createShell(self, request, node, data): |  | 
| 65         """Create a `shell' node that will hold the additional form |  | 
| 66         elements, if one is required. |  | 
| 67         """ |  | 
| 68         return lmx(node).table(border="0") |  | 
| 69 |  | 
| 70     def input_single(self, request, content, model, templateAttributes={}): |  | 
| 71         """ |  | 
| 72         Returns a text input node built based upon the node model. |  | 
| 73         Optionally takes an already-coded DOM node merges that |  | 
| 74         information with the model's information.  Returns a new (??) |  | 
| 75         lmx node. |  | 
| 76         """ |  | 
| 77         #in a text field, only the following options are allowed (well, more |  | 
| 78         #are, but they're not supported yet - can add them in later) |  | 
| 79         attribs = ['type', 'name', 'value', 'size', 'maxlength', |  | 
| 80                    'readonly'] #only MSIE recognizes readonly and disabled |  | 
| 81 |  | 
| 82         arguments = {} |  | 
| 83         for attrib in attribs: |  | 
| 84             #model hints and values override anything in the template |  | 
| 85             val = model.getHint(attrib, templateAttributes.get(attrib, None)) |  | 
| 86             if val: |  | 
| 87                 arguments[attrib] = str(val) |  | 
| 88 |  | 
| 89         value = self.getValue(request, model) |  | 
| 90         if value: |  | 
| 91             arguments["value"] = str(value) |  | 
| 92 |  | 
| 93         arguments["type"] = "text"  #these are default |  | 
| 94         arguments["name"] = model.name |  | 
| 95 |  | 
| 96         return content.input(**arguments) |  | 
| 97 |  | 
| 98     def input_string(self, request, content, model, templateAttributes={}): |  | 
| 99         if not templateAttributes.has_key("size"): |  | 
| 100             templateAttributes["size"] = '60' |  | 
| 101         return self.input_single(request, content, model, templateAttributes) |  | 
| 102 |  | 
| 103     input_integer = input_single |  | 
| 104     input_integerrange = input_single |  | 
| 105     input_float = input_single |  | 
| 106 |  | 
| 107     def input_text(self, request, content, model, templateAttributes={}): |  | 
| 108         r = content.textarea( |  | 
| 109             cols=str(model.getHint('cols', |  | 
| 110                                    templateAttributes.get('cols', '60'))), |  | 
| 111             rows=str(model.getHint('rows', |  | 
| 112                                    templateAttributes.get('rows', '10'))), |  | 
| 113             name=model.name, |  | 
| 114             wrap=str(model.getHint('wrap', |  | 
| 115                                    templateAttributes.get('wrap', "virtual")))) |  | 
| 116         r.text(str(self.getValue(request, model))) |  | 
| 117         return r |  | 
| 118 |  | 
| 119     def input_hidden(self, request, content, model, templateAttributes={}): |  | 
| 120         return content.input(type="hidden", |  | 
| 121                              name=model.name, |  | 
| 122                              value=str(self.getValue(request, model))) |  | 
| 123 |  | 
| 124     def input_submit(self, request, content, model, templateAttributes={}): |  | 
| 125         arguments = {} |  | 
| 126         val = model.getHint("onClick", templateAttributes.get("onClick", None)) |  | 
| 127         if val: |  | 
| 128             arguments["onClick"] = val |  | 
| 129         arguments["type"] = "submit" |  | 
| 130         arguments["name"] = model.name |  | 
| 131         div = content.div() |  | 
| 132         for tag, value, desc in model.choices: |  | 
| 133             args = arguments.copy() |  | 
| 134             args["value"] = tag |  | 
| 135             div.input(**args) |  | 
| 136             div.text(" ") |  | 
| 137         if model.reset: |  | 
| 138             div.input(type="reset") |  | 
| 139         return div |  | 
| 140 |  | 
| 141     def input_choice(self, request, content, model, templateAttributes={}): |  | 
| 142         # am I not evil? allow onChange js events |  | 
| 143         arguments = {} |  | 
| 144         val = model.getHint("onChange", templateAttributes.get("onChange", None)
     ) |  | 
| 145         if val: |  | 
| 146             arguments["onChange"] = val |  | 
| 147         arguments["name"] = model.name |  | 
| 148         s = content.select(**arguments) |  | 
| 149         default = self.getValues(request, model) |  | 
| 150         for tag, value, desc in model.choices: |  | 
| 151             kw = {} |  | 
| 152             if value in default: |  | 
| 153                 kw = {'selected' : '1'} |  | 
| 154             s.option(value=tag, **kw).text(desc) |  | 
| 155         return s |  | 
| 156 |  | 
| 157     def input_group(self, request, content, model, groupValues, inputType, |  | 
| 158                     templateAttributes={}): |  | 
| 159         """ |  | 
| 160         Base code for a group of objects.  Checkgroup will use this, as |  | 
| 161         well as radiogroup.  In the attributes, rows means how many rows |  | 
| 162         the group should be arranged into, cols means how many cols the |  | 
| 163         group should be arranged into.  Columns take precedence over |  | 
| 164         rows: if both are specified, the output will always generate the |  | 
| 165         correct number of columns.  However, if the number of elements |  | 
| 166         in the group exceed (or is smaller than) rows*cols, then the |  | 
| 167         number of rows will be off.  A cols attribute of 1 will mean that |  | 
| 168         all the elements will be listed one underneath another.  The |  | 
| 169         default is a rows attribute of 1:  everything listed next to each |  | 
| 170         other. |  | 
| 171         """ |  | 
| 172         rows = model.getHint('rows', templateAttributes.get('rows', None)) |  | 
| 173         cols = model.getHint('cols', templateAttributes.get('cols', None)) |  | 
| 174         if rows: |  | 
| 175             rows = int(rows) |  | 
| 176         if cols: |  | 
| 177             cols = int(cols) |  | 
| 178 |  | 
| 179         defaults = self.getValues(request, model) |  | 
| 180         if (rows and rows>1) or (cols and cols>1):  #build a table |  | 
| 181             s = content.table(border="0") |  | 
| 182             if cols: |  | 
| 183                 breakat = cols |  | 
| 184             else: |  | 
| 185                 breakat = math.ceil(float(len(groupValues))/rows) |  | 
| 186             for i in range(0, len(groupValues), breakat): |  | 
| 187                 tr = s.tr() |  | 
| 188                 for j in range(0, breakat): |  | 
| 189                     if i+j >= len(groupValues): |  | 
| 190                         break |  | 
| 191                     tag, value, desc = groupValues[i+j] |  | 
| 192                     kw = {} |  | 
| 193                     if value in defaults: |  | 
| 194                         kw = {'checked' : '1'} |  | 
| 195                     tr.td().input(type=inputType, name=model.name, |  | 
| 196                         value=tag, **kw).text(desc) |  | 
| 197 |  | 
| 198         else: |  | 
| 199             s = content.div() |  | 
| 200             for tag, value, desc in groupValues: |  | 
| 201                 kw = {} |  | 
| 202                 if value in defaults: |  | 
| 203                     kw = {'checked' : '1'} |  | 
| 204                 s.input(type=inputType, name=model.name, |  | 
| 205                         value=tag, **kw).text(desc) |  | 
| 206                 if cols: |  | 
| 207                     s.br() |  | 
| 208 |  | 
| 209         return s |  | 
| 210 |  | 
| 211     def input_checkgroup(self, request, content, model, templateAttributes={}): |  | 
| 212         return self.input_group(request, content, model, model.flags, |  | 
| 213                                 "checkbox", templateAttributes) |  | 
| 214 |  | 
| 215     def input_radiogroup(self, request, content, model, templateAttributes={}): |  | 
| 216         return self.input_group(request, content, model, model.choices, |  | 
| 217                                 "radio", templateAttributes) |  | 
| 218 |  | 
| 219     #I don't know why they're the same, but they were.  So I removed the |  | 
| 220     #excess code.  Maybe someone should look into removing it entirely. |  | 
| 221     input_flags = input_checkgroup |  | 
| 222 |  | 
| 223     def input_boolean(self, request, content, model, templateAttributes={}): |  | 
| 224         kw = {} |  | 
| 225         if self.getValue(request, model): |  | 
| 226             kw = {'checked' : '1'} |  | 
| 227         return content.input(type="checkbox", name=model.name, **kw) |  | 
| 228 |  | 
| 229     def input_file(self, request, content, model, templateAttributes={}): |  | 
| 230         kw = {} |  | 
| 231         for attrib in ['size', 'accept']: |  | 
| 232             val = model.getHint(attrib, templateAttributes.get(attrib, None)) |  | 
| 233             if val: |  | 
| 234                 kw[attrib] = str(val) |  | 
| 235         return content.input(type="file", name=model.name, **kw) |  | 
| 236 |  | 
| 237     def input_date(self, request, content, model, templateAttributes={}): |  | 
| 238         breakLines = model.getHint('breaklines', 1) |  | 
| 239         date = self.getValues(request, model) |  | 
| 240         if date == None: |  | 
| 241             year, month, day = "", "", "" |  | 
| 242         else: |  | 
| 243             year, month, day = date |  | 
| 244         div = content.div() |  | 
| 245         div.text("Year: ") |  | 
| 246         div.input(type="text", size="4", maxlength="4", name=model.name, value=s
     tr(year)) |  | 
| 247         if breakLines: |  | 
| 248             div.br() |  | 
| 249         div.text("Month: ") |  | 
| 250         div.input(type="text", size="2", maxlength="2", name=model.name, value=s
     tr(month)) |  | 
| 251         if breakLines: |  | 
| 252             div.br() |  | 
| 253         div.text("Day: ") |  | 
| 254         div.input(type="text", size="2", maxlength="2", name=model.name, value=s
     tr(day)) |  | 
| 255         return div |  | 
| 256 |  | 
| 257     def input_password(self, request, content, model, templateAttributes={}): |  | 
| 258         return content.input( |  | 
| 259             type="password", |  | 
| 260             size=str(templateAttributes.get('size', "60")), |  | 
| 261             name=model.name) |  | 
| 262 |  | 
| 263     def input_verifiedpassword(self, request, content, model, templateAttributes
     ={}): |  | 
| 264         breakLines = model.getHint('breaklines', 1) |  | 
| 265         values = self.getValues(request, model) |  | 
| 266         if isinstance(values, (str, unicode)): |  | 
| 267             values = (values, values) |  | 
| 268         if not values: |  | 
| 269             p1, p2 = "", "" |  | 
| 270         elif len(values) == 1: |  | 
| 271             p1, p2 = values, "" |  | 
| 272         elif len(values) == 2: |  | 
| 273             p1, p2 = values |  | 
| 274         else: |  | 
| 275             p1, p2 = "", "" |  | 
| 276         div = content.div() |  | 
| 277         div.text("Password: ") |  | 
| 278         div.input(type="password", size="20", name=model.name, value=str(p1)) |  | 
| 279         if breakLines: |  | 
| 280             div.br() |  | 
| 281         div.text("Verify: ") |  | 
| 282         div.input(type="password", size="20", name=model.name, value=str(p2)) |  | 
| 283         return div |  | 
| 284 |  | 
| 285 |  | 
| 286     def convergeInput(self, request, content, model, templateNode): |  | 
| 287         name = model.__class__.__name__.lower() |  | 
| 288         if _renderers.has_key(model.__class__): |  | 
| 289             imeth = _renderers[model.__class__] |  | 
| 290         else: |  | 
| 291             imeth = getattr(self,"input_"+name) |  | 
| 292 |  | 
| 293         return imeth(request, content, model, templateNode.attributes).node |  | 
| 294 |  | 
| 295     def createInput(self, request, shell, model, templateAttributes={}): |  | 
| 296         name = model.__class__.__name__.lower() |  | 
| 297         if _renderers.has_key(model.__class__): |  | 
| 298             imeth = _renderers[model.__class__] |  | 
| 299         else: |  | 
| 300             imeth = getattr(self,"input_"+name) |  | 
| 301         if name in self.SPANNING_TYPES: |  | 
| 302             td = shell.tr().td(valign="top", colspan="2") |  | 
| 303             return (imeth(request, td, model).node, shell.tr().td(colspan="2").n
     ode) |  | 
| 304         else: |  | 
| 305             if model.allowNone: |  | 
| 306                 required = "" |  | 
| 307             else: |  | 
| 308                 required = " *" |  | 
| 309             tr = shell.tr() |  | 
| 310             tr.td(align="right", valign="top").text(model.getShortDescription()+
     ":"+required) |  | 
| 311             content = tr.td(valign="top") |  | 
| 312             return (imeth(request, content, model).node, |  | 
| 313                     content.div(_class="formDescription"). # because class is a 
     keyword |  | 
| 314                     text(model.getLongDescription()).node) |  | 
| 315 |  | 
| 316     def setUp(self, request, node, data): |  | 
| 317         # node = widgets.Widget.generateDOM(self,request,node) |  | 
| 318         lmn = lmx(node) |  | 
| 319         if not node.hasAttribute('action'): |  | 
| 320             lmn['action'] = (request.prepath+request.postpath)[-1] |  | 
| 321         if not node.hasAttribute("method"): |  | 
| 322             lmn['method'] = 'post' |  | 
| 323         lmn['enctype'] = 'multipart/form-data' |  | 
| 324         self.errorNodes = errorNodes = {}                     # name: nodes whic
     h trap errors |  | 
| 325         self.inputNodes = inputNodes = {} |  | 
| 326         for errorNode in domhelpers.findElementsWithAttribute(node, 'errorFor'): |  | 
| 327             errorNodes[errorNode.getAttribute('errorFor')] = errorNode |  | 
| 328         argz={} |  | 
| 329         # list to figure out which nodes are in the template already and which a
     ren't |  | 
| 330         hasSubmit = 0 |  | 
| 331         argList = self.model.fmethod.getArgs() |  | 
| 332         for arg in argList: |  | 
| 333             if isinstance(arg, formmethod.Submit): |  | 
| 334                 hasSubmit = 1 |  | 
| 335             argz[arg.name] = arg |  | 
| 336         inNodes = domhelpers.findElements( |  | 
| 337             node, |  | 
| 338             lambda n: n.tagName.lower() in ('textarea', 'select', 'input', |  | 
| 339                                             'div')) |  | 
| 340         for inNode in inNodes: |  | 
| 341             t = inNode.getAttribute("type") |  | 
| 342             if t and t.lower() == "submit": |  | 
| 343                 hasSubmit = 1 |  | 
| 344             if not inNode.hasAttribute("name"): |  | 
| 345                 continue |  | 
| 346             nName = inNode.getAttribute("name") |  | 
| 347             if argz.has_key(nName): |  | 
| 348                 #send an empty content shell - we just want the node |  | 
| 349                 inputNodes[nName] = self.convergeInput(request, lmx(), |  | 
| 350                                                        argz[nName], inNode) |  | 
| 351                 inNode.parentNode.replaceChild(inputNodes[nName], inNode) |  | 
| 352                 del argz[nName] |  | 
| 353             # TODO: |  | 
| 354             # * some arg types should only have a single node (text, string, etc
     ) |  | 
| 355             # * some should have multiple nodes (choice, checkgroup) |  | 
| 356             # * some have a bunch of ancillary nodes that are possible values (m
     enu, radiogroup) |  | 
| 357             # these should all be taken into account when walking through the te
     mplate |  | 
| 358         if argz: |  | 
| 359             shell = self.createShell(request, node, data) |  | 
| 360             # create inputs, in the same order they were passed to us: |  | 
| 361             for remArg in [arg for arg in argList if argz.has_key(arg.name)]: |  | 
| 362                 inputNode, errorNode = self.createInput(request, shell, remArg) |  | 
| 363                 errorNodes[remArg.name] = errorNode |  | 
| 364                 inputNodes[remArg.name] = inputNode |  | 
| 365 |  | 
| 366         if not hasSubmit: |  | 
| 367             lmn.input(type="submit") |  | 
| 368 |  | 
| 369 |  | 
| 370 class FormErrorWidget(FormFillerWidget): |  | 
| 371     def setUp(self, request, node, data): |  | 
| 372         FormFillerWidget.setUp(self, request, node, data) |  | 
| 373         for k, f in self.model.err.items(): |  | 
| 374             en = self.errorNodes[k] |  | 
| 375             tn = self.inputNodes[k] |  | 
| 376             en.setAttribute('class', 'formError') |  | 
| 377             tn.setAttribute('class', 'formInputError') |  | 
| 378             en.childNodes[:]=[] # gurfle, CLEAR IT NOW!@# |  | 
| 379             if isinstance(f, failure.Failure): |  | 
| 380                 f = f.getErrorMessage() |  | 
| 381             lmx(en).text(str(f)) |  | 
| 382 |  | 
| 383 |  | 
| 384 class FormDisplayModel(model.MethodModel): |  | 
| 385     def initialize(self, fmethod, alwaysDefault=False): |  | 
| 386         self.fmethod = fmethod |  | 
| 387         self.alwaysDefault = alwaysDefault |  | 
| 388 |  | 
| 389 class FormErrorModel(FormDisplayModel): |  | 
| 390     def initialize(self, fmethod, args, err): |  | 
| 391         FormDisplayModel.initialize(self, fmethod) |  | 
| 392         self.args = args |  | 
| 393         if isinstance(err, failure.Failure): |  | 
| 394             err = err.value |  | 
| 395         if isinstance(err, Exception): |  | 
| 396             self.err = getattr(err, "descriptions", {}) |  | 
| 397             self.desc = err |  | 
| 398         else: |  | 
| 399             self.err = err |  | 
| 400             self.desc = "Please try again" |  | 
| 401 |  | 
| 402     def wmfactory_description(self, request): |  | 
| 403         return str(self.desc) |  | 
| 404 |  | 
| 405 class _RequestHack(model.MethodModel): |  | 
| 406     def wmfactory_hack(self, request): |  | 
| 407         rv = [[str(a), repr(b)] for (a, b) |  | 
| 408               in request._outDict.items()] |  | 
| 409         #print 'hack', rv |  | 
| 410         return rv |  | 
| 411 |  | 
| 412 class FormProcessor(resource.Resource): |  | 
| 413     def __init__(self, formMethod, callback=None, errback=None): |  | 
| 414         resource.Resource.__init__(self) |  | 
| 415         self.formMethod = formMethod |  | 
| 416         if callback is None: |  | 
| 417             callback = self.viewFactory |  | 
| 418         self.callback = callback |  | 
| 419         if errback is None: |  | 
| 420             errback = self.errorViewFactory |  | 
| 421         self.errback = errback |  | 
| 422 |  | 
| 423     def getArgs(self, request): |  | 
| 424         """Return the formmethod.Arguments. |  | 
| 425 |  | 
| 426         Overridable hook to allow pre-processing, e.g. if we want to enable |  | 
| 427         on them depending on one of the inputs. |  | 
| 428         """ |  | 
| 429         return self.formMethod.getArgs() |  | 
| 430 |  | 
| 431     def render(self, request): |  | 
| 432         outDict = {} |  | 
| 433         errDict = {} |  | 
| 434         for methodArg in self.getArgs(request): |  | 
| 435             valmethod = getattr(self,"mangle_"+ |  | 
| 436                                 (methodArg.__class__.__name__.lower()), None) |  | 
| 437             tmpval = request.args.get(methodArg.name) |  | 
| 438             if valmethod: |  | 
| 439                 # mangle the argument to a basic datatype that coerce will like |  | 
| 440                 tmpval = valmethod(tmpval) |  | 
| 441             # coerce it |  | 
| 442             try: |  | 
| 443                 cv = methodArg.coerce(tmpval) |  | 
| 444                 outDict[methodArg.name] = cv |  | 
| 445             except: |  | 
| 446                 errDict[methodArg.name] = failure.Failure() |  | 
| 447         if errDict: |  | 
| 448             # there were problems processing the form |  | 
| 449             return self.errback(self.errorModelFactory( |  | 
| 450                 request.args, outDict, errDict)).render(request) |  | 
| 451         else: |  | 
| 452             try: |  | 
| 453                 if self.formMethod.takesRequest: |  | 
| 454                     outObj = self.formMethod.call(request=request, **outDict) |  | 
| 455                 else: |  | 
| 456                     outObj = self.formMethod.call(**outDict) |  | 
| 457             except formmethod.FormException, e: |  | 
| 458                 err = request.errorInfo = self.errorModelFactory( |  | 
| 459                     request.args, outDict, e) |  | 
| 460                 return self.errback(err).render(request) |  | 
| 461             else: |  | 
| 462                 request._outDict = outDict # CHOMP CHOMP! |  | 
| 463                 # I wanted better default behavior for debugging, so I could |  | 
| 464                 # see the arguments passed, but there is no channel for this in |  | 
| 465                 # the existing callback structure.  So, here it goes. |  | 
| 466                 if isinstance(outObj, defer.Deferred): |  | 
| 467                     def _ebModel(err): |  | 
| 468                         if err.trap(formmethod.FormException): |  | 
| 469                             mf = self.errorModelFactory(request.args, outDict, |  | 
| 470                                                         err.value) |  | 
| 471                             return self.errback(mf) |  | 
| 472                         raise err |  | 
| 473                     (outObj |  | 
| 474                      .addCallback(self.modelFactory) |  | 
| 475                      .addCallback(self.callback) |  | 
| 476                      .addErrback(_ebModel)) |  | 
| 477                     return util.DeferredResource(outObj).render(request) |  | 
| 478                 else: |  | 
| 479                     return self.callback(self.modelFactory(outObj)).render( |  | 
| 480                         request) |  | 
| 481 |  | 
| 482     def errorModelFactory(self, args, out, err): |  | 
| 483         return FormErrorModel(self.formMethod, args, err) |  | 
| 484 |  | 
| 485     def errorViewFactory(self, m): |  | 
| 486         v = view.View(m) |  | 
| 487         v.template = ''' |  | 
| 488         <html> |  | 
| 489         <head> |  | 
| 490         <title> Form Error View </title> |  | 
| 491         <style> |  | 
| 492         .formDescription {color: green} |  | 
| 493         .formError {color: red; font-weight: bold} |  | 
| 494         .formInputError {color: #900} |  | 
| 495         </style> |  | 
| 496         </head> |  | 
| 497         <body> |  | 
| 498         Error: <span model="description" /> |  | 
| 499         <form model="."> |  | 
| 500         </form> |  | 
| 501         </body> |  | 
| 502         </html> |  | 
| 503         ''' |  | 
| 504         return v |  | 
| 505 |  | 
| 506     def modelFactory(self, outObj): |  | 
| 507         adapt = interfaces.IModel(outObj, outObj) |  | 
| 508         # print 'factorizing', adapt |  | 
| 509         return adapt |  | 
| 510 |  | 
| 511     def viewFactory(self, model): |  | 
| 512         # return interfaces.IView(model) |  | 
| 513         if model is None: |  | 
| 514             bodyStr = ''' |  | 
| 515             <table model="hack" style="background-color: #99f"> |  | 
| 516             <tr pattern="listItem" view="Widget"> |  | 
| 517             <td model="0" style="font-weight: bold"> |  | 
| 518             </td> |  | 
| 519             <td model="1"> |  | 
| 520             </td> |  | 
| 521             </tr> |  | 
| 522             </table> |  | 
| 523             ''' |  | 
| 524             model = _RequestHack() |  | 
| 525         else: |  | 
| 526             bodyStr = '<div model="." />' |  | 
| 527         v = view.View(model) |  | 
| 528         v.template = ''' |  | 
| 529         <html> |  | 
| 530         <head> |  | 
| 531         <title> Thank You </title> |  | 
| 532         </head> |  | 
| 533         <body> |  | 
| 534         <h1>Thank You for Using Woven</h1> |  | 
| 535         %s |  | 
| 536         </body> |  | 
| 537         </html> |  | 
| 538         ''' % bodyStr |  | 
| 539         return v |  | 
| 540 |  | 
| 541     # manglizers |  | 
| 542 |  | 
| 543     def mangle_single(self, args): |  | 
| 544         if args: |  | 
| 545             return args[0] |  | 
| 546         else: |  | 
| 547             return '' |  | 
| 548 |  | 
| 549     mangle_string = mangle_single |  | 
| 550     mangle_text = mangle_single |  | 
| 551     mangle_integer = mangle_single |  | 
| 552     mangle_password = mangle_single |  | 
| 553     mangle_integerrange = mangle_single |  | 
| 554     mangle_float = mangle_single |  | 
| 555     mangle_choice = mangle_single |  | 
| 556     mangle_boolean = mangle_single |  | 
| 557     mangle_hidden = mangle_single |  | 
| 558     mangle_submit = mangle_single |  | 
| 559     mangle_file = mangle_single |  | 
| 560     mangle_radiogroup = mangle_single |  | 
| 561 |  | 
| 562     def mangle_multi(self, args): |  | 
| 563         if args is None: |  | 
| 564             return [] |  | 
| 565         return args |  | 
| 566 |  | 
| 567     mangle_checkgroup = mangle_multi |  | 
| 568     mangle_flags = mangle_multi |  | 
| 569 |  | 
| 570 from twisted.python.formmethod import FormMethod |  | 
| 571 |  | 
| 572 view.registerViewForModel(FormFillerWidget, FormDisplayModel) |  | 
| 573 view.registerViewForModel(FormErrorWidget, FormErrorModel) |  | 
| 574 registerAdapter(FormDisplayModel, FormMethod, interfaces.IModel) |  | 
| 575 |  | 
| OLD | NEW | 
|---|