On Mon, Oct 25, 2010 at 08:45:27AM +0530, Anand Chitipothu wrote:
> 2010/10/21 Daniel Garcia Moreno <[email protected]>:
> > 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.
> 
> Looks good. Couple of comments:
> 
> * Can you try implementing this without using metaclass magic?
> 
> * I think it is better to specify validators using attribute
> "validators" instead of adding each validator as an attribute or using
> __validators__. Like this:
> 
> class MyForm(form.Form):
>     name = form.TextboxField()
>     password = form.PasswordField()
>     password2 = form.PasswordField()
> 
>     validators = [
>         form.Validator("Passwords didn't match.", lambda i: i.password
> == i.password2)
>     ]

Here's the patch modified, withouth magic and using validators attribute
instead of __validators__.
From 7836db9557c8d569536386b235ca274bbdbacc2f 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 |   84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/web/form.py b/web/form.py
index 1ea60ad..30e68fd 100644
--- a/web/form.py
+++ b/web/form.py
@@ -22,9 +22,24 @@ 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 hasattr(self, 'validators'):
+            self.validators = []
+        self.validators += kw.pop('validators', [])
 
     def __call__(self, x=None):
         o = copy.deepcopy(self)
@@ -110,6 +125,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 +139,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 +376,53 @@ class File(Input):
     """
     def get_type(self):
         return 'file'
-    
+
+
+class TextboxField(Textbox):
+    def __init__(self, *args, **kwargs):
+        super(TextboxField, self).__init__(self, '', *args, **kwargs)
+
+
+class PasswordField(Password):
+    def __init__(self, *args, **kwargs):
+        super(PasswordField, self).__init__(self, '', *args, **kwargs)
+
+
+class TextareaField(Textarea):
+    def __init__(self, *args, **kwargs):
+        super(TextareaField, self).__init__(self, '', *args, **kwargs)
+
+
+class DropdownField(Dropdown):
+    def __init__(self, *args, **kwargs):
+        super(DropdownField, self).__init__(self, '', *args, **kwargs)
+
+
+class RadioField(Radio):
+    def __init__(self, *args, **kwargs):
+        super(RadioField, self).__init__(self, '', *args, **kwargs)
+
+
+class CheckboxField(Checkbox):
+    def __init__(self, *args, **kwargs):
+        super(CheckboxField, self).__init__(self, '', *args, **kwargs)
+
+
+class ButtonField(Button):
+    def __init__(self, *args, **kwargs):
+        super(ButtonField, self).__init__(self, '', *args, **kwargs)
+
+
+class HiddenField(Hidden):
+    def __init__(self, *args, **kwargs):
+        super(HiddenField, self).__init__(self, '', *args, **kwargs)
+
+
+class FileField(File):
+    def __init__(self, *args, **kwargs):
+        super(FileField, self).__init__(self, '', *args, **kwargs)
+
+
 class Validator:
     def __deepcopy__(self, memo): return copy.copy(self)
     def __init__(self, msg, test, jstest=None): utils.autoassign(self, locals())
-- 
1.7.1

Attachment: signature.asc
Description: Digital signature

Reply via email to