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

Reply via email to