""" Form classes """ from fields import Field from widgets import TextInput, Textarea from util import ErrorDict, ErrorList, ValidationError NON_FIELD_ERRORS = '__all__' def pretty_name(name): "Converts 'first_name' to 'First name'" name = name[0].upper() + name[1:] return name.replace('_', ' ') class DeclarativeFieldsMetaclass(type): "Metaclass that converts Field attributes to a dictionary called 'fields'." def __new__(cls, name, bases, attrs): attrs['fields'] = dict([(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)]) return type.__new__(cls, name, bases, attrs) class Form(object): "A collection of Fields, plus their associated data." __metaclass__ = DeclarativeFieldsMetaclass def __init__(self, data=None): # TODO: prefix stuff self.data = data or {} self.clean_data = None # Stores the data after clean() has been called. self.__errors = None # Stores the errors after clean() has been called. def __str__(self): return self.as_table() def __iter__(self): for name, field in self.fields.items(): yield BoundField(self, field, name) def __getitem__(self, name): "Returns a BoundField with the given name." try: field = self.fields[name] except KeyError: raise KeyError('Key %r not found in Form' % name) return BoundField(self, field, name) def clean(self): if self.__errors is None: self.full_clean() return self.clean_data def errors(self): "Returns an ErrorDict for self.data" if self.__errors is None: self.full_clean() return self.__errors def is_valid(self): """ Returns True if the form has no errors. Otherwise, False. This exists solely for convenience, so client code can use positive logic rather than confusing negative logic ("if not form.errors()"). """ return not bool(self.errors()) def as_table(self): "Returns this form rendered as an HTML ." output = u'\n'.join(['' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()]) return '
%s:%s
\n%s\n
' % output def as_ul(self): "Returns this form rendered as an HTML