El mié, 20-10-2010 a las 13:46 -0700, Justin Davis escribió:
> Ah, clarification, since you use "dir" you will get an alphabetical
> list of the inputs. At least this is deterministic, though the order
> is still not defined by the user.
>
> On Oct 20, 1:43 pm, Justin Davis <[email protected]> wrote:
> > Correct me if I'm wrong, but I don't think this preserves the input
> > order. getattr will just try to access the __dict__ of the object (and
> > then the parent, etc), but it won't preserve order of the output. This
> > means that calling render on that object will produce weird layouts.
> >
I fix that, now fields are ordered. I also make the sintax more clear,
andrei commented that it would be much better if you didn't have to name
your inputs twice, and I fixed it too. But for that I need to create
other classes inside form because Input requires name param in __init__
method.
The new syntax is like that:
from web import form
class MyForm(form.Form):
name = form.TextboxField()
password = form.PasswordField()
password2 = form.PasswordField()
validator1 = form.Validator("Passwords didn't match.", lambda i:
i.password == i.password2)
And you can define validators as a list using __validators__ attr.
As you can see, I don't use normal form.Input, I use inputname plus
Field that is a class that inherit from the Input but has an __init__
method that don't need name as first argument.
--
You received this message because you are subscribed to the Google Groups
"web.py" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/webpy?hl=en.
>From bd9ed4f6e17542edc64d18e471c9f32494e8a5d4 Mon Sep 17 00:00:00 2001
From: Daniel Garcia <[email protected]>
Date: Thu, 21 Oct 2010 11:10:40 +0200
Subject: [PATCH] Allow declare forms using inheritance.
---
web/form.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/web/form.py b/web/form.py
index 1ea60ad..43098b7 100644
--- a/web/form.py
+++ b/web/form.py
@@ -3,6 +3,7 @@ HTML forms
(part of web.py)
"""
+import types
import copy, re
import webapi as web
import utils, net
@@ -22,9 +23,28 @@ class Form:
"""
def __init__(self, *inputs, **kw):
self.inputs = inputs
+ if not self.inputs:
+ self.inputs = []
+
+ # Getting input class attributes
+ is_input = lambda x: hasattr(self, x) and\
+ isinstance(getattr(self, x), Input)
+ for i in filter(is_input, dir(self)):
+ inp = getattr(self, i)
+ if not inp.name:
+ inp.set_name(i)
+ self.inputs.append(inp)
+ self.inputs.sort(key=lambda x: x.creation_counter)
+
self.valid = True
self.note = None
self.validators = kw.pop('validators', [])
+ if not self.validators:
+ self.validators = [getattr(self, i) for i in dir(self) if\
+ hasattr(self, i) and\
+ isinstance(getattr(self, i), Validator)]
+ if hasattr(self, '__validators__'):
+ self.validators += self.__validators__
def __call__(self, x=None):
o = copy.deepcopy(self)
@@ -110,6 +130,9 @@ class Form:
d = property(_get_d)
class Input(object):
+
+ creation_counter = 0
+
def __init__(self, name, *validators, **attrs):
self.name = name
self.validators = validators
@@ -121,12 +144,24 @@ class Input(object):
self.post = attrs.pop('post', "")
self.note = None
- self.id = attrs.setdefault('id', self.get_default_id())
+ self.creation_counter = Input.creation_counter
+ Input.creation_counter += 1
+
+ if self.get_default_id():
+ self.id = attrs.setdefault('id', self.get_default_id())
+ else:
+ self.id = ''
if 'class_' in attrs:
attrs['class'] = attrs['class_']
del attrs['class_']
-
+
+ def set_name(self, name):
+ self.name = name
+ self.id = self.attrs.setdefault('id', self.get_default_id())
+ if not self.description:
+ self.description = self.name
+
def is_hidden(self):
return False
@@ -346,7 +381,26 @@ class File(Input):
"""
def get_type(self):
return 'file'
-
+
+
+class MetaInput(type):
+
+ def __init__(cls, name, bases, dct):
+ base = bases[0]
+ def new_init(self, *args, **kwargs):
+ base.__init__(self, '', *args, **kwargs)
+
+ type.__init__(cls, name, bases, dct)
+ cls.__init__ = new_init
+
+
+allclasses = vars().copy()
+for name, klass in allclasses.items():
+ if type(klass) in [types.ClassType, types.TypeType] and issubclass(klass, Input):
+ klass_name = name + 'Field'
+ vars()[klass_name] = MetaInput(klass_name, (klass, ), {})
+
+
class Validator:
def __deepcopy__(self, memo): return copy.copy(self)
def __init__(self, msg, test, jstest=None): utils.autoassign(self, locals())
--
1.7.1