""" HTML forms (part of web.py) """ import copy, re import webapi as web import utils, net def attrget(obj, attr, value=None): if hasattr(obj, 'has_key') and obj.has_key(attr): return obj[attr] if hasattr(obj, attr): return getattr(obj, attr) return value class Form: r""" HTML form. >>> f = Form(Textbox("x")) >>> f.render() '\n \n
' """ def __init__(self, *inputs, **kw): self.inputs = inputs self.valid = True self.note = None self.validators = kw.pop('validators', []) def __call__(self, x=None): o = copy.deepcopy(self) if x: o.validates(x) return o def render(self): out = '' out += self.rendernote(self.note) out += '\n' for i in self.inputs: out += ' ' % (i.id, net.websafe(i.description)) out += "\n" out += "
"+i.pre+i.render()+i.post+"
" return out def render_css(self): out = [] out.append(self.rendernote(self.note)) for i in self.inputs: out.append('' % (i.id, net.websafe(i.description))) out.append(i.pre) out.append(i.render()) out.append(i.post) out.append('\n') return ''.join(out) def rendernote(self, note): if note: return '%s' % net.websafe(note) else: return "" def validates(self, source=None, _validate=True, **kw): source = source or kw or web.input() out = True for i in self.inputs: v = attrget(source, i.name) if _validate: out = i.validate(v) and out else: i.value = v if _validate: out = out and self._validate(source) self.valid = out return out def _validate(self, value): self.value = value for v in self.validators: if not v.valid(value): self.note = v.msg return False return True def fill(self, source=None, **kw): return self.validates(source, _validate=False, **kw) def __getitem__(self, i): for x in self.inputs: if x.name == i: return x raise KeyError, i def __getattr__(self, name): # don't interfere with deepcopy inputs = self.__dict__.get('inputs') or [] for x in inputs: if x.name == name: return x raise AttributeError, name def get(self, i, default=None): try: return self[i] except KeyError: return default def _get_d(self): #@@ should really be form.attr, no? return utils.storage([(i.name, i.value) for i in self.inputs]) d = property(_get_d) class Input(object): def __init__(self, name, *validators, **attrs): self.description = attrs.pop('description', name) self.value = attrs.pop('value', None) self.pre = attrs.pop('pre', "") self.post = attrs.pop('post', "") self.id = attrs.setdefault('id', name) if 'class_' in attrs: attrs['class'] = attrs['class_'] del attrs['class_'] self.name, self.validators, self.attrs, self.note = name, validators, attrs, None def validate(self, value): self.value = value for v in self.validators: if not v.valid(value): self.note = v.msg return False return True def render(self): raise NotImplementedError def rendernote(self, note): if note: return '%s' % net.websafe(note) else: return "" def addatts(self): str = "" for (n, v) in self.attrs.items(): str += ' %s="%s"' % (n, net.websafe(v)) return str #@@ quoting class Textbox(Input): def render(self, shownote=True): x = '