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
signature.asc
Description: Digital signature
