Commits

Anonymous committed 6ca9424

generic-auth: Merged to trunk [4254]

Comments (0)

Files changed (47)

     Manuzhai
     Petar Marić
     mark@junklight.com
+    Yasushi Masuda <whosaysni@gmail.com>
     mattycakes@gmail.com
     Jason McBrayer <http://www.carcosa.net/jason/>
     mccutchen@gmail.com
     michael.mcewan@gmail.com
+    mitakummaa@gmail.com
     mmarshall
     Eric Moritz <http://eric.themoritzfamily.com/>
     Robin Munn <http://www.geekforgod.com/>
     Tom Insam
     Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
     Karen Tracey <graybark@bellsouth.net>
+    Makoto Tsuyuki <mtsuyuki@gmail.com>
     Amit Upadhyay
     Geert Vanderkelen
     Milton Waddams

django/conf/global_settings.py

 INTERNAL_IPS = ()
 
 # Local time zone for this installation. All choices can be found here:
-# http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
+# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
 TIME_ZONE = 'America/Chicago'
 
 # Language code for this installation. All choices can be found here:

django/conf/project_template/settings.py

 DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.
 
 # Local time zone for this installation. All choices can be found here:
-# http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
+# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
 TIME_ZONE = 'America/Chicago'
 
 # Language code for this installation. All choices can be found here:

django/contrib/admin/templates/admin/base.html

     <div id="content" class="{% block coltype %}colM{% endblock %}">
         {% block pretitle %}{% endblock %}
         {% block content_title %}{% if title %}<h1>{{ title|escape }}</h1>{% endif %}{% endblock %}
-        {% block content %}{{ content }}{% endblock %}
+        {% block content %}
+        {% block object-tools %}{% endblock %}
+        {{ content }}
+        {% endblock %}
         {% block sidebar %}{% endblock %}
         <br class="clear" />
     </div>

django/contrib/admin/templates/admin/change_form.html

 </div>
 {% endif %}{% endblock %}
 {% block content %}<div id="content-main">
+{% block object-tools %}
 {% if change %}{% if not is_popup %}
   <ul class="object-tools"><li><a href="history/" class="historylink">{% trans "History" %}</a></li>
   {% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
   </ul>
 {% endif %}{% endif %}
+{% endblock %}
 <form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
 <div>
 {% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}

django/contrib/admin/templates/admin/change_list.html

 {% block coltype %}flex{% endblock %}
 {% block content %}
 <div id="content-main">
+{% block object-tools %}
 {% if has_add_permission %}
 <ul class="object-tools"><li><a href="add/{% if is_popup %}?_popup=1{% endif %}" class="addlink">{% blocktrans with cl.opts.verbose_name|escape as name %}Add {{ name }}{% endblocktrans %}</a></li></ul>
 {% endif %}
+{% endblock %}
 <div class="module{% if cl.has_filters %} filtered{% endif %}" id="changelist">
 {% block search %}{% search_form cl %}{% endblock %}
 {% block date_hierarchy %}{% date_hierarchy cl %}{% endblock %}

django/contrib/admin/views/auth.py

 from django.contrib.auth.forms import UserCreationForm
 from django.contrib.auth.models import User
 from django.core.exceptions import PermissionDenied
-from django import forms, template
+from django import oldforms, template
 from django.shortcuts import render_to_response
 from django.http import HttpResponseRedirect
 
                 return HttpResponseRedirect('../%s/' % new_user.id)
     else:
         errors = new_data = {}
-    form = forms.FormWrapper(manipulator, new_data, errors)
+    form = oldforms.FormWrapper(manipulator, new_data, errors)
     return render_to_response('admin/auth/user/add_form.html', {
         'title': _('Add user'),
         'form': form,

django/contrib/admin/views/main.py

-from django import forms, template
+from django import oldforms, template
 from django.conf import settings
 from django.contrib.auth import has_permission
 from django.contrib.admin.filterspecs import FilterSpec
         errors = {}
 
     # Populate the FormWrapper.
-    form = forms.FormWrapper(manipulator, new_data, errors)
+    form = oldforms.FormWrapper(manipulator, new_data, errors)
 
     c = template.RequestContext(request, {
         'title': _('Add %s') % opts.verbose_name,
         errors = {}
 
     # Populate the FormWrapper.
-    form = forms.FormWrapper(manipulator, new_data, errors)
+    form = oldforms.FormWrapper(manipulator, new_data, errors)
     form.original = manipulator.original_object
     form.order_objects = []
 

django/contrib/admin/views/template.py

 from django.contrib.admin.views.decorators import staff_member_required
 from django.core import validators
-from django import template, forms
+from django import template, oldforms
 from django.template import loader
 from django.shortcuts import render_to_response
 from django.contrib.sites.models import Site
             request.user.message_set.create(message='The template is valid.')
     return render_to_response('admin/template_validator.html', {
         'title': 'Template validator',
-        'form': forms.FormWrapper(manipulator, new_data, errors),
+        'form': oldforms.FormWrapper(manipulator, new_data, errors),
     }, context_instance=template.RequestContext(request))
 template_validator = staff_member_required(template_validator)
 
-class TemplateValidator(forms.Manipulator):
+class TemplateValidator(oldforms.Manipulator):
     def __init__(self, settings_modules):
         self.settings_modules = settings_modules
         site_list = Site.objects.in_bulk(settings_modules.keys()).values()
         self.fields = (
-            forms.SelectField('site', is_required=True, choices=[(s.id, s.name) for s in site_list]),
-            forms.LargeTextField('template', is_required=True, rows=25, validator_list=[self.isValidTemplate]),
+            oldforms.SelectField('site', is_required=True, choices=[(s.id, s.name) for s in site_list]),
+            oldforms.LargeTextField('template', is_required=True, rows=25, validator_list=[self.isValidTemplate]),
         )
 
     def isValidTemplate(self, field_data, all_data):

django/contrib/auth/forms.py

 from django.contrib.sites.models import Site
 from django.template import Context, loader
 from django.core import validators
-from django import forms
+from django import oldforms
 
-class UserCreationForm(forms.Manipulator):
+class UserCreationForm(oldforms.Manipulator):
     "A form that creates a user, with no privileges, from the given username and password."
     def __init__(self):
         self.fields = (
-            forms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
+            oldforms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
                 validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
-            forms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
-            forms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
+            oldforms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
+            oldforms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
                 validator_list=[validators.AlwaysMatchesOtherField('password1', _("The two password fields didn't match."))]),
         )
 
         "Creates the user."
         return User.objects.create_user(new_data['username'], '', new_data['password1'])
 
-class AuthenticationForm(forms.Manipulator):
+class AuthenticationForm(oldforms.Manipulator):
     """
     Base class for authenticating users. Extend this to get a form that accepts
     username/password logins.
         """
         self.request = request
         self.fields = [
-            forms.TextField(field_name="username", length=15, maxlength=30, is_required=True,
+            oldforms.TextField(field_name="username", length=15, maxlength=30, is_required=True,
                 validator_list=[self.isValidUser, self.hasCookiesEnabled]),
-            forms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True),
+            oldforms.PasswordField(field_name="password", length=15, maxlength=30, is_required=True),
         ]
         self.user_cache = None
 
     def get_user(self):
         return self.user_cache
 
-class PasswordResetForm(forms.Manipulator):
+class PasswordResetForm(oldforms.Manipulator):
     "A form that lets a user request a password reset"
     def __init__(self):
         self.fields = (
-            forms.EmailField(field_name="email", length=40, is_required=True,
+            oldforms.EmailField(field_name="email", length=40, is_required=True,
                 validator_list=[self.isValidUserEmail]),
         )
 
         }
         send_mail('Password reset on %s' % site_name, t.render(Context(c)), None, [self.user_cache.email])
 
-class PasswordChangeForm(forms.Manipulator):
+class PasswordChangeForm(oldforms.Manipulator):
     "A form that lets a user change his password."
     def __init__(self, user):
         self.user = user
         self.fields = (
-            forms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True,
+            oldforms.PasswordField(field_name="old_password", length=30, maxlength=30, is_required=True,
                 validator_list=[self.isValidOldPassword]),
-            forms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True,
+            oldforms.PasswordField(field_name="new_password1", length=30, maxlength=30, is_required=True,
                 validator_list=[validators.AlwaysMatchesOtherField('new_password2', _("The two 'new password' fields didn't match."))]),
-            forms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True),
+            oldforms.PasswordField(field_name="new_password2", length=30, maxlength=30, is_required=True),
         )
 
     def isValidOldPassword(self, new_data, all_data):

django/contrib/auth/views.py

 from django.contrib.auth.forms import AuthenticationForm
 from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm
-from django import forms
+from django import oldforms
 from django.shortcuts import render_to_response
 from django.template import RequestContext
 from django.contrib.sites.models import Site
         errors = {}
     request.session.set_test_cookie()
     return render_to_response(template_name, {
-        'form': forms.FormWrapper(manipulator, request.POST, errors),
+        'form': oldforms.FormWrapper(manipulator, request.POST, errors),
         REDIRECT_FIELD_NAME: redirect_to,
         'site_name': Site.objects.get_current().name,
     }, context_instance=RequestContext(request))
             else:
                 form.save(email_template_name=email_template_name)
             return HttpResponseRedirect('%sdone/' % request.path)
-    return render_to_response(template_name, {'form': forms.FormWrapper(form, new_data, errors)},
+    return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)},
         context_instance=RequestContext(request))
 
 def password_reset_done(request, template_name='registration/password_reset_done.html'):
         if not errors:
             form.save(new_data)
             return HttpResponseRedirect('%sdone/' % request.path)
-    return render_to_response(template_name, {'form': forms.FormWrapper(form, new_data, errors)},
+    return render_to_response(template_name, {'form': oldforms.FormWrapper(form, new_data, errors)},
         context_instance=RequestContext(request))
 password_change = login_required(password_change)
 

django/contrib/comments/views/comments.py

 from django.core import validators
-from django import forms
+from django import oldforms
 from django.core.mail import mail_admins, mail_managers
 from django.http import Http404
 from django.core.exceptions import ObjectDoesNotExist
             else:
                 return []
         self.fields.extend([
-            forms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
+            oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
                 validator_list=[self.hasNoProfanities]),
-            forms.RadioSelectField(field_name="rating1", choices=choices,
+            oldforms.RadioSelectField(field_name="rating1", choices=choices,
                 is_required=ratings_required and num_rating_choices > 0,
                 validator_list=get_validator_list(1),
             ),
-            forms.RadioSelectField(field_name="rating2", choices=choices,
+            oldforms.RadioSelectField(field_name="rating2", choices=choices,
                 is_required=ratings_required and num_rating_choices > 1,
                 validator_list=get_validator_list(2),
             ),
-            forms.RadioSelectField(field_name="rating3", choices=choices,
+            oldforms.RadioSelectField(field_name="rating3", choices=choices,
                 is_required=ratings_required and num_rating_choices > 2,
                 validator_list=get_validator_list(3),
             ),
-            forms.RadioSelectField(field_name="rating4", choices=choices,
+            oldforms.RadioSelectField(field_name="rating4", choices=choices,
                 is_required=ratings_required and num_rating_choices > 3,
                 validator_list=get_validator_list(4),
             ),
-            forms.RadioSelectField(field_name="rating5", choices=choices,
+            oldforms.RadioSelectField(field_name="rating5", choices=choices,
                 is_required=ratings_required and num_rating_choices > 4,
                 validator_list=get_validator_list(5),
             ),
-            forms.RadioSelectField(field_name="rating6", choices=choices,
+            oldforms.RadioSelectField(field_name="rating6", choices=choices,
                 is_required=ratings_required and num_rating_choices > 5,
                 validator_list=get_validator_list(6),
             ),
-            forms.RadioSelectField(field_name="rating7", choices=choices,
+            oldforms.RadioSelectField(field_name="rating7", choices=choices,
                 is_required=ratings_required and num_rating_choices > 6,
                 validator_list=get_validator_list(7),
             ),
-            forms.RadioSelectField(field_name="rating8", choices=choices,
+            oldforms.RadioSelectField(field_name="rating8", choices=choices,
                 is_required=ratings_required and num_rating_choices > 7,
                 validator_list=get_validator_list(8),
             ),
             mail_managers("Comment posted by sketchy user (%s)" % self.user_cache.username, c.get_as_text())
         return c
 
-class PublicFreeCommentManipulator(forms.Manipulator):
+class PublicFreeCommentManipulator(oldforms.Manipulator):
     "Manipulator that handles public free (unregistered) comments"
     def __init__(self):
         self.fields = (
-            forms.TextField(field_name="person_name", maxlength=50, is_required=True,
+            oldforms.TextField(field_name="person_name", maxlength=50, is_required=True,
                 validator_list=[self.hasNoProfanities]),
-            forms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
+            oldforms.LargeTextField(field_name="comment", maxlength=3000, is_required=True,
                 validator_list=[self.hasNoProfanities]),
         )
 
         from django.contrib.auth import login
         login(request, manipulator.get_user())
     if errors or request.POST.has_key('preview'):
-        class CommentFormWrapper(forms.FormWrapper):
+        class CommentFormWrapper(oldforms.FormWrapper):
             def __init__(self, manipulator, new_data, errors, rating_choices):
-                forms.FormWrapper.__init__(self, manipulator, new_data, errors)
+                oldforms.FormWrapper.__init__(self, manipulator, new_data, errors)
                 self.rating_choices = rating_choices
             def ratings(self):
                 field_list = [self['rating%d' % (i+1)] for i in range(len(rating_choices))]
         comment = errors and '' or manipulator.get_comment(new_data)
         return render_to_response('comments/free_preview.html', {
             'comment': comment,
-            'comment_form': forms.FormWrapper(manipulator, new_data, errors),
+            'comment_form': oldforms.FormWrapper(manipulator, new_data, errors),
             'options': options,
             'target': target,
             'hash': security_hash,

django/contrib/csrf/middleware.py

 import re
 import itertools
 
-_ERROR_MSG = "<h1>403 Forbidden</h1><p>Cross Site Request Forgery detected.  Request aborted.</p>"
+_ERROR_MSG = '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"><body><h1>403 Forbidden</h1><p>Cross Site Request Forgery detected. Request aborted.</p></body></html>'
 
 _POST_FORM_RE = \
     re.compile(r'(<form\W[^>]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)', re.IGNORECASE)

django/core/handlers/base.py

             if response:
                 return response
 
-        resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
+        # Get urlconf from request object, if available.  Otherwise use default.
+        urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
+
+        resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
         try:
             callback, callback_args, callback_kwargs = resolver.resolve(request.path)
 

django/db/backends/postgresql/base.py

     # Import copy of _thread_local.py from Python 2.4
     from django.utils._threading_local import local
 
+def smart_basestring(s, charset):
+    if isinstance(s, unicode):
+        return s.encode(charset)
+    return s
+
+class UnicodeCursorWrapper(object):
+    """
+    A thin wrapper around psycopg cursors that allows them to accept Unicode
+    strings as params.
+
+    This is necessary because psycopg doesn't apply any DB quoting to
+    parameters that are Unicode strings. If a param is Unicode, this will
+    convert it to a bytestring using DEFAULT_CHARSET before passing it to
+    psycopg.
+    """
+    def __init__(self, cursor, charset):
+        self.cursor = cursor
+        self.charset = charset
+
+    def execute(self, sql, params=()):
+        return self.cursor.execute(sql, [smart_basestring(p, self.charset) for p in params])
+
+    def executemany(self, sql, param_list):
+        new_param_list = [[smart_basestring(p, self.charset) for p in params] for params in param_list]
+        return self.cursor.executemany(sql, new_param_list)
+
+    def __getattr__(self, attr):
+        if self.__dict__.has_key(attr):
+            return self.__dict__[attr]
+        else:
+            return getattr(self.cursor, attr)
+
 class DatabaseWrapper(local):
     def __init__(self, **kwargs):
         self.connection = None
             self.connection.set_isolation_level(1) # make transactions transparent to all cursors
         cursor = self.connection.cursor()
         cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
+        cursor = UnicodeCursorWrapper(cursor, settings.DEFAULT_CHARSET)
         if settings.DEBUG:
             return util.CursorDebugWrapper(cursor, self)
         return cursor
 try:
     Database.register_type(Database.new_type((1082,), "DATE", util.typecast_date))
 except AttributeError:
-    raise Exception, "You appear to be using psycopg version 2, which isn't supported yet, because it's still in beta. Use psycopg version 1 instead: http://initd.org/projects/psycopg1"
+    raise Exception, "You appear to be using psycopg version 2. Set your DATABASE_ENGINE to 'postgresql_psycopg2' instead of 'postgresql'."
 Database.register_type(Database.new_type((1083,1266), "TIME", util.typecast_time))
 Database.register_type(Database.new_type((1114,1184), "TIMESTAMP", util.typecast_timestamp))
 Database.register_type(Database.new_type((16,), "BOOLEAN", util.typecast_boolean))

django/db/models/fields/__init__.py

 from django.dispatch import dispatcher
 from django.conf import settings
 from django.core import validators
-from django import forms
+from django import oldforms
+from django import newforms as forms
 from django.core.exceptions import ObjectDoesNotExist
 from django.utils.functional import curry
 from django.utils.itercompat import tee
 
         if self.choices:
             if self.radio_admin:
-                field_objs = [forms.RadioSelectField]
+                field_objs = [oldforms.RadioSelectField]
                 params['ul_class'] = get_ul_class(self.radio_admin)
             else:
-                field_objs = [forms.SelectField]
+                field_objs = [oldforms.SelectField]
 
             params['choices'] = self.get_choices_default()
         else:
 
     def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
         """
-        Returns a list of forms.FormField instances for this field. It
+        Returns a list of oldforms.FormField instances for this field. It
         calculates the choices at runtime, not at compile time.
 
         name_prefix is a prefix to prepend to the "field_name" argument.
             return self._choices
     choices = property(_get_choices)
 
+    def formfield(self, initial=None):
+        "Returns a django.newforms.Field instance for this database Field."
+        # TODO: This is just a temporary default during development.
+        return forms.CharField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
+    def value_from_object(self, obj):
+        "Returns the value of this field in the given model instance."
+        return getattr(obj, self.attname)
+
 class AutoField(Field):
     empty_strings_allowed = False
     def __init__(self, *args, **kwargs):
         return Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)
 
     def get_manipulator_field_objs(self):
-        return [forms.HiddenField]
+        return [oldforms.HiddenField]
 
     def get_manipulator_new_data(self, new_data, rel=False):
         # Never going to be called
         super(AutoField, self).contribute_to_class(cls, name)
         cls._meta.has_auto_field = True
 
+    def formfield(self, initial=None):
+        return None
+
 class BooleanField(Field):
     def __init__(self, *args, **kwargs):
         kwargs['blank'] = True
         raise validators.ValidationError, gettext("This value must be either True or False.")
 
     def get_manipulator_field_objs(self):
-        return [forms.CheckboxField]
+        return [oldforms.CheckboxField]
+
+    def formfield(self, initial=None):
+        return forms.BooleanField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
 
 class CharField(Field):
     def get_manipulator_field_objs(self):
-        return [forms.TextField]
+        return [oldforms.TextField]
 
     def to_python(self, value):
         if isinstance(value, basestring):
                 raise validators.ValidationError, gettext_lazy("This field cannot be null.")
         return str(value)
 
+    def formfield(self, initial=None):
+        return forms.CharField(max_length=self.maxlength, required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 # TODO: Maybe move this into contrib, because it's specialized.
 class CommaSeparatedIntegerField(CharField):
     def get_manipulator_field_objs(self):
-        return [forms.CommaSeparatedIntegerField]
+        return [oldforms.CommaSeparatedIntegerField]
 
 class DateField(Field):
     empty_strings_allowed = False
         return Field.get_db_prep_save(self, value)
 
     def get_manipulator_field_objs(self):
-        return [forms.DateField]
+        return [oldforms.DateField]
 
-    def flatten_data(self, follow, obj = None):
+    def flatten_data(self, follow, obj=None):
         val = self._get_val_from_obj(obj)
         return {self.attname: (val is not None and val.strftime("%Y-%m-%d") or '')}
 
+    def formfield(self, initial=None):
+        return forms.DateField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 class DateTimeField(DateField):
     def to_python(self, value):
         if isinstance(value, datetime.datetime):
         return Field.get_db_prep_lookup(self, lookup_type, value)
 
     def get_manipulator_field_objs(self):
-        return [forms.DateField, forms.TimeField]
+        return [oldforms.DateField, oldforms.TimeField]
 
     def get_manipulator_field_names(self, name_prefix):
         return [name_prefix + self.name + '_date', name_prefix + self.name + '_time']
         return {date_field: (val is not None and val.strftime("%Y-%m-%d") or ''),
                 time_field: (val is not None and val.strftime("%H:%M:%S") or '')}
 
+    def formfield(self, initial=None):
+        return forms.DateTimeField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 class EmailField(CharField):
     def __init__(self, *args, **kwargs):
         kwargs['maxlength'] = 75
         return "CharField"
 
     def get_manipulator_field_objs(self):
-        return [forms.EmailField]
+        return [oldforms.EmailField]
 
     def validate(self, field_data, all_data):
         validators.isValidEmail(field_data, all_data)
 
+    def formfield(self, initial=None):
+        return forms.EmailField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 class FileField(Field):
     def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):
         self.upload_to = upload_to
                 os.remove(file_name)
 
     def get_manipulator_field_objs(self):
-        return [forms.FileUploadField, forms.HiddenField]
+        return [oldforms.FileUploadField, oldforms.HiddenField]
 
     def get_manipulator_field_names(self, name_prefix):
         return [name_prefix + self.name + '_file', name_prefix + self.name]
         Field.__init__(self, verbose_name, name, **kwargs)
 
     def get_manipulator_field_objs(self):
-        return [curry(forms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)]
+        return [curry(oldforms.FilePathField, path=self.path, match=self.match, recursive=self.recursive)]
 
 class FloatField(Field):
     empty_strings_allowed = False
         Field.__init__(self, verbose_name, name, **kwargs)
 
     def get_manipulator_field_objs(self):
-        return [curry(forms.FloatField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
+        return [curry(oldforms.FloatField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
 
 class ImageField(FileField):
     def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):
         FileField.__init__(self, verbose_name, name, **kwargs)
 
     def get_manipulator_field_objs(self):
-        return [forms.ImageUploadField, forms.HiddenField]
+        return [oldforms.ImageUploadField, oldforms.HiddenField]
 
     def contribute_to_class(self, cls, name):
         super(ImageField, self).contribute_to_class(cls, name)
 class IntegerField(Field):
     empty_strings_allowed = False
     def get_manipulator_field_objs(self):
-        return [forms.IntegerField]
+        return [oldforms.IntegerField]
+
+    def formfield(self, initial=None):
+        return forms.IntegerField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
 
 class IPAddressField(Field):
     def __init__(self, *args, **kwargs):
         Field.__init__(self, *args, **kwargs)
 
     def get_manipulator_field_objs(self):
-        return [forms.IPAddressField]
+        return [oldforms.IPAddressField]
 
     def validate(self, field_data, all_data):
         validators.isValidIPAddress4(field_data, None)
         Field.__init__(self, *args, **kwargs)
 
     def get_manipulator_field_objs(self):
-        return [forms.NullBooleanField]
+        return [oldforms.NullBooleanField]
 
 class PhoneNumberField(IntegerField):
     def get_manipulator_field_objs(self):
-        return [forms.PhoneNumberField]
+        return [oldforms.PhoneNumberField]
 
     def validate(self, field_data, all_data):
         validators.isValidPhone(field_data, all_data)
 
 class PositiveIntegerField(IntegerField):
     def get_manipulator_field_objs(self):
-        return [forms.PositiveIntegerField]
+        return [oldforms.PositiveIntegerField]
 
 class PositiveSmallIntegerField(IntegerField):
     def get_manipulator_field_objs(self):
-        return [forms.PositiveSmallIntegerField]
+        return [oldforms.PositiveSmallIntegerField]
 
 class SlugField(Field):
     def __init__(self, *args, **kwargs):
         Field.__init__(self, *args, **kwargs)
 
     def get_manipulator_field_objs(self):
-        return [forms.TextField]
+        return [oldforms.TextField]
 
 class SmallIntegerField(IntegerField):
     def get_manipulator_field_objs(self):
-        return [forms.SmallIntegerField]
+        return [oldforms.SmallIntegerField]
 
 class TextField(Field):
     def get_manipulator_field_objs(self):
-        return [forms.LargeTextField]
+        return [oldforms.LargeTextField]
 
 class TimeField(Field):
     empty_strings_allowed = False
         return Field.get_db_prep_save(self, value)
 
     def get_manipulator_field_objs(self):
-        return [forms.TimeField]
+        return [oldforms.TimeField]
 
     def flatten_data(self,follow, obj = None):
         val = self._get_val_from_obj(obj)
         return {self.attname: (val is not None and val.strftime("%H:%M:%S") or '')}
 
+    def formfield(self, initial=None):
+        return forms.TimeField(required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 class URLField(Field):
     def __init__(self, verbose_name=None, name=None, verify_exists=True, **kwargs):
         if verify_exists:
             kwargs.setdefault('validator_list', []).append(validators.isExistingURL)
+        self.verify_exists = verify_exists
         Field.__init__(self, verbose_name, name, **kwargs)
 
     def get_manipulator_field_objs(self):
-        return [forms.URLField]
+        return [oldforms.URLField]
+
+    def formfield(self, initial=None):
+        return forms.URLField(required=not self.blank, verify_exists=self.verify_exists, label=capfirst(self.verbose_name), initial=initial)
 
 class USStateField(Field):
     def get_manipulator_field_objs(self):
-        return [forms.USStateField]
+        return [oldforms.USStateField]
 
 class XMLField(TextField):
     def __init__(self, verbose_name=None, name=None, schema_path=None, **kwargs):
         return "TextField"
 
     def get_manipulator_field_objs(self):
-        return [curry(forms.XMLLargeTextField, schema_path=self.schema_path)]
+        return [curry(oldforms.XMLLargeTextField, schema_path=self.schema_path)]
 
 class OrderingField(IntegerField):
     empty_strings_allowed=False
         return "IntegerField"
 
     def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
-        return [forms.HiddenField(name_prefix + self.name)]
+        return [oldforms.HiddenField(name_prefix + self.name)]

django/db/models/fields/generic.py

 Classes allowing "generic" relations through ContentType and object-id fields.
 """
 
-from django import forms
+from django import oldforms
 from django.core.exceptions import ObjectDoesNotExist
 from django.db import backend
 from django.db.models import signals
 
     def get_manipulator_field_objs(self):
         choices = self.get_choices_default()
-        return [curry(forms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
+        return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
 
     def get_choices_default(self):
         return Field.get_choices(self, include_blank=False)

django/db/models/fields/related.py

 from django.db.models import signals, get_model
 from django.db.models.fields import AutoField, Field, IntegerField, get_ul_class
 from django.db.models.related import RelatedObject
+from django.utils.text import capfirst
 from django.utils.translation import gettext_lazy, string_concat, ngettext
 from django.utils.functional import curry
 from django.core import validators
-from django import forms
+from django import oldforms
+from django import newforms as forms
 from django.dispatch import dispatcher
 
 # For Python 2.3
         # Otherwise, just move the named objects into the set.
         if self.related.field.null:
             manager.clear()
-        for obj in value:
-            manager.add(obj)
+        manager.add(*value)
 
 def create_many_related_manager(superclass):
     """Creates a manager that subclasses 'superclass' (which is a Manager)
             # *objs - objects to add
             from django.db import connection
 
-            # Add the newly created or already existing objects to the join table.
-            # First find out which items are already added, to avoid adding them twice
-            new_ids = set([obj._get_pk_val() for obj in objs])
-            cursor = connection.cursor()
-            cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \
-                (target_col_name, self.join_table, source_col_name,
-                target_col_name, ",".join(['%s'] * len(new_ids))),
-                [self._pk_val] + list(new_ids))
-            if cursor.rowcount is not None and cursor.rowcount != 0:
-                existing_ids = set([row[0] for row in cursor.fetchmany(cursor.rowcount)])
-            else:
-                existing_ids = set()
+            # If there aren't any objects, there is nothing to do.
+            if objs:
+                # Check that all the objects are of the right type
+                for obj in objs:
+                    if not isinstance(obj, self.model):
+                        raise ValueError, "objects to add() must be %s instances" % self.model._meta.object_name
+                # Add the newly created or already existing objects to the join table.
+                # First find out which items are already added, to avoid adding them twice
+                new_ids = set([obj._get_pk_val() for obj in objs])
+                cursor = connection.cursor()
+                cursor.execute("SELECT %s FROM %s WHERE %s = %%s AND %s IN (%s)" % \
+                    (target_col_name, self.join_table, source_col_name,
+                    target_col_name, ",".join(['%s'] * len(new_ids))),
+                    [self._pk_val] + list(new_ids))
+                if cursor.rowcount is not None and cursor.rowcount != 0:
+                    existing_ids = set([row[0] for row in cursor.fetchmany(cursor.rowcount)])
+                else:
+                    existing_ids = set()
 
-            # Add the ones that aren't there already
-            for obj_id in (new_ids - existing_ids):
-                cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
-                    (self.join_table, source_col_name, target_col_name),
-                    [self._pk_val, obj_id])
-            transaction.commit_unless_managed()
+                # Add the ones that aren't there already
+                for obj_id in (new_ids - existing_ids):
+                    cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
+                        (self.join_table, source_col_name, target_col_name),
+                        [self._pk_val, obj_id])
+                transaction.commit_unless_managed()
 
         def _remove_items(self, source_col_name, target_col_name, *objs):
             # source_col_name: the PK colname in join_table for the source object
             # *objs - objects to remove
             from django.db import connection
 
-            for obj in objs:
-                if not isinstance(obj, self.model):
-                    raise ValueError, "objects to remove() must be %s instances" % self.model._meta.object_name
-            # Remove the specified objects from the join table
-            cursor = connection.cursor()
-            for obj in objs:
-                cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s = %%s" % \
-                    (self.join_table, source_col_name, target_col_name),
-                    [self._pk_val, obj._get_pk_val()])
-            transaction.commit_unless_managed()
+            # If there aren't any objects, there is nothing to do.
+            if objs:
+                # Check that all the objects are of the right type
+                for obj in objs:
+                    if not isinstance(obj, self.model):
+                        raise ValueError, "objects to remove() must be %s instances" % self.model._meta.object_name
+                # Remove the specified objects from the join table
+                old_ids = set([obj._get_pk_val() for obj in objs])
+                cursor = connection.cursor()
+                cursor.execute("DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \
+                    (self.join_table, source_col_name,
+                    target_col_name, ",".join(['%s'] * len(old_ids))),
+                    [self._pk_val] + list(old_ids))
+                transaction.commit_unless_managed()
 
         def _clear_items(self, source_col_name):
             # source_col_name: the PK colname in join_table for the source object
 
         manager = self.__get__(instance)
         manager.clear()
-        for obj in value:
-            manager.add(obj)
+        manager.add(*value)
 
 class ReverseManyRelatedObjectsDescriptor(object):
     # This class provides the functionality that makes the related-object
 
         manager = self.__get__(instance)
         manager.clear()
-        for obj in value:
-            manager.add(obj)
+        manager.add(*value)
 
 class ForeignKey(RelatedField, Field):
     empty_strings_allowed = False
             params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator))
         else:
             if self.radio_admin:
-                field_objs = [forms.RadioSelectField]
+                field_objs = [oldforms.RadioSelectField]
                 params['ul_class'] = get_ul_class(self.radio_admin)
             else:
                 if self.null:
-                    field_objs = [forms.NullSelectField]
+                    field_objs = [oldforms.NullSelectField]
                 else:
-                    field_objs = [forms.SelectField]
+                    field_objs = [oldforms.SelectField]
             params['choices'] = self.get_choices_default()
         return field_objs, params
 
         if self.rel.raw_id_admin and not isinstance(rel_field, AutoField):
             return rel_field.get_manipulator_field_objs()
         else:
-            return [forms.IntegerField]
+            return [oldforms.IntegerField]
 
     def get_db_prep_save(self, value):
         if value == '' or value == None:
     def contribute_to_related_class(self, cls, related):
         setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
 
+    def formfield(self, initial=None):
+        return forms.ChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 class OneToOneField(RelatedField, IntegerField):
     def __init__(self, to, to_field=None, **kwargs):
         try:
             params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator))
         else:
             if self.radio_admin:
-                field_objs = [forms.RadioSelectField]
+                field_objs = [oldforms.RadioSelectField]
                 params['ul_class'] = get_ul_class(self.radio_admin)
             else:
                 if self.null:
-                    field_objs = [forms.NullSelectField]
+                    field_objs = [oldforms.NullSelectField]
                 else:
-                    field_objs = [forms.SelectField]
+                    field_objs = [oldforms.SelectField]
             params['choices'] = self.get_choices_default()
         return field_objs, params
 
         if not cls._meta.one_to_one_field:
             cls._meta.one_to_one_field = self
 
+    def formfield(self, initial=None):
+        return forms.ChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 class ManyToManyField(RelatedField, Field):
     def __init__(self, to, **kwargs):
         kwargs['verbose_name'] = kwargs.get('verbose_name', None)
 
     def get_manipulator_field_objs(self):
         if self.rel.raw_id_admin:
-            return [forms.RawIdAdminField]
+            return [oldforms.RawIdAdminField]
         else:
             choices = self.get_choices_default()
-            return [curry(forms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
+            return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
 
     def get_choices_default(self):
         return Field.get_choices(self, include_blank=False)
     def set_attributes_from_rel(self):
         pass
 
+    def value_from_object(self, obj):
+        "Returns the value of this field in the given model instance."
+        return getattr(obj, self.attname).all()
+
+    def formfield(self, initial=None):
+        return forms.MultipleChoiceField(choices=self.get_choices_default(), required=not self.blank, label=capfirst(self.verbose_name), initial=initial)
+
 class ManyToOneRel(object):
     def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
         max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,

django/db/models/manipulators.py

 from django.core.exceptions import ObjectDoesNotExist
-from django import forms
+from django import oldforms
 from django.core import validators
 from django.db.models.fields import FileField, AutoField
 from django.dispatch import dispatcher
                 self.man._prepare(model)
             return self.man
 
-class AutomaticManipulator(forms.Manipulator):
+class AutomaticManipulator(oldforms.Manipulator):
     def _prepare(cls, model):
         cls.model = model
         cls.manager = model._default_manager
 
         # Add field for ordering.
         if self.change and self.opts.get_ordered_objects():
-            self.fields.append(forms.CommaSeparatedIntegerField(field_name="order_"))
+            self.fields.append(oldforms.CommaSeparatedIntegerField(field_name="order_"))
 
     def save(self, new_data):
         # TODO: big cleanup when core fields go -> use recursive manipulators.
 def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data):
     from django.db.models.fields.related import ManyToOneRel
     date_str = all_data.get(date_field.get_manipulator_field_names('')[0], None)
-    date_val = forms.DateField.html2python(date_str)
+    date_val = oldforms.DateField.html2python(date_str)
     if date_val is None:
         return # Date was invalid. This will be caught by another validator.
     lookup_kwargs = {'%s__year' % date_field.name: date_val.year}

django/forms/__init__.py

-from django.core import validators
-from django.core.exceptions import PermissionDenied
-from django.utils.html import escape
-from django.conf import settings
-from django.utils.translation import gettext, ngettext
-
-FORM_FIELD_ID_PREFIX = 'id_'
-
-class EmptyValue(Exception):
-    "This is raised when empty data is provided"
-    pass
-
-class Manipulator(object):
-    # List of permission strings. User must have at least one to manipulate.
-    # None means everybody has permission.
-    required_permission = ''
-
-    def __init__(self):
-        # List of FormField objects
-        self.fields = []
-
-    def __getitem__(self, field_name):
-        "Looks up field by field name; raises KeyError on failure"
-        for field in self.fields:
-            if field.field_name == field_name:
-                return field
-        raise KeyError, "Field %s not found\n%s" % (field_name, repr(self.fields))
-
-    def __delitem__(self, field_name):
-        "Deletes the field with the given field name; raises KeyError on failure"
-        for i, field in enumerate(self.fields):
-            if field.field_name == field_name:
-                del self.fields[i]
-                return
-        raise KeyError, "Field %s not found" % field_name
-
-    def check_permissions(self, user):
-        """Confirms user has required permissions to use this manipulator; raises
-        PermissionDenied on failure."""
-        if self.required_permission is None:
-            return
-        if user.has_perm(self.required_permission):
-            return
-        raise PermissionDenied
-
-    def prepare(self, new_data):
-        """
-        Makes any necessary preparations to new_data, in place, before data has
-        been validated.
-        """
-        for field in self.fields:
-            field.prepare(new_data)
-
-    def get_validation_errors(self, new_data):
-        "Returns dictionary mapping field_names to error-message lists"
-        errors = {}
-        self.prepare(new_data)
-        for field in self.fields:
-            errors.update(field.get_validation_errors(new_data))
-            val_name = 'validate_%s' % field.field_name
-            if hasattr(self, val_name):
-                val = getattr(self, val_name)
-                try:
-                    field.run_validator(new_data, val)
-                except (validators.ValidationError, validators.CriticalValidationError), e:
-                    errors.setdefault(field.field_name, []).extend(e.messages)
-
-#            if field.is_required and not new_data.get(field.field_name, False):
-#                errors.setdefault(field.field_name, []).append(gettext_lazy('This field is required.'))
-#                continue
-#            try:
-#                validator_list = field.validator_list
-#                if hasattr(self, 'validate_%s' % field.field_name):
-#                    validator_list.append(getattr(self, 'validate_%s' % field.field_name))
-#                for validator in validator_list:
-#                    if field.is_required or new_data.get(field.field_name, False) or hasattr(validator, 'always_test'):
-#                        try:
-#                            if hasattr(field, 'requires_data_list'):
-#                                validator(new_data.getlist(field.field_name), new_data)
-#                            else:
-#                                validator(new_data.get(field.field_name, ''), new_data)
-#                        except validators.ValidationError, e:
-#                            errors.setdefault(field.field_name, []).extend(e.messages)
-#            # If a CriticalValidationError is raised, ignore any other ValidationErrors
-#            # for this particular field
-#            except validators.CriticalValidationError, e:
-#                errors.setdefault(field.field_name, []).extend(e.messages)
-        return errors
-
-    def save(self, new_data):
-        "Saves the changes and returns the new object"
-        # changes is a dictionary-like object keyed by field_name
-        raise NotImplementedError
-
-    def do_html2python(self, new_data):
-        """
-        Convert the data from HTML data types to Python datatypes, changing the
-        object in place. This happens after validation but before storage. This
-        must happen after validation because html2python functions aren't
-        expected to deal with invalid input.
-        """
-        for field in self.fields:
-            field.convert_post_data(new_data)
-
-class FormWrapper(object):
-    """
-    A wrapper linking a Manipulator to the template system.
-    This allows dictionary-style lookups of formfields. It also handles feeding
-    prepopulated data and validation error messages to the formfield objects.
-    """
-    def __init__(self, manipulator, data=None, error_dict=None, edit_inline=True):
-        self.manipulator = manipulator
-        if data is None:
-            data = {}
-        if error_dict is None:
-            error_dict = {}
-        self.data = data
-        self.error_dict = error_dict
-        self._inline_collections = None
-        self.edit_inline = edit_inline
-
-    def __repr__(self):
-        return repr(self.__dict__)
-
-    def __getitem__(self, key):
-        for field in self.manipulator.fields:
-            if field.field_name == key:
-                data = field.extract_data(self.data)
-                return FormFieldWrapper(field, data, self.error_dict.get(field.field_name, []))
-        if self.edit_inline:
-            self.fill_inline_collections()
-            for inline_collection in self._inline_collections:
-                if inline_collection.name == key:
-                    return inline_collection
-        raise KeyError, "Could not find Formfield or InlineObjectCollection named %r" % key
-
-    def fill_inline_collections(self):
-        if not self._inline_collections:
-            ic = []
-            related_objects = self.manipulator.get_related_objects()
-            for rel_obj in related_objects:
-                data = rel_obj.extract_data(self.data)
-                inline_collection = InlineObjectCollection(self.manipulator, rel_obj, data, self.error_dict)
-                ic.append(inline_collection)
-            self._inline_collections = ic
-
-    def has_errors(self):
-        return self.error_dict != {}
-
-    def _get_fields(self):
-        try:
-            return self._fields
-        except AttributeError:
-            self._fields = [self.__getitem__(field.field_name) for field in self.manipulator.fields]
-            return self._fields
-
-    fields = property(_get_fields)
-
-class FormFieldWrapper(object):
-    "A bridge between the template system and an individual form field. Used by FormWrapper."
-    def __init__(self, formfield, data, error_list):
-        self.formfield, self.data, self.error_list = formfield, data, error_list
-        self.field_name = self.formfield.field_name # for convenience in templates
-
-    def __str__(self):
-        "Renders the field"
-        return str(self.formfield.render(self.data))
-
-    def __repr__(self):
-        return '<FormFieldWrapper for "%s">' % self.formfield.field_name
-
-    def field_list(self):
-        """
-        Like __str__(), but returns a list. Use this when the field's render()
-        method returns a list.
-        """
-        return self.formfield.render(self.data)
-
-    def errors(self):
-        return self.error_list
-
-    def html_error_list(self):
-        if self.errors():
-            return '<ul class="errorlist"><li>%s</li></ul>' % '</li><li>'.join([escape(e) for e in self.errors()])
-        else:
-            return ''
-
-    def get_id(self):
-        return self.formfield.get_id()
-
-class FormFieldCollection(FormFieldWrapper):
-    "A utility class that gives the template access to a dict of FormFieldWrappers"
-    def __init__(self, formfield_dict):
-        self.formfield_dict = formfield_dict
-
-    def __str__(self):
-        return str(self.formfield_dict)
-
-    def __getitem__(self, template_key):
-        "Look up field by template key; raise KeyError on failure"
-        return self.formfield_dict[template_key]
-
-    def __repr__(self):
-        return "<FormFieldCollection: %s>" % self.formfield_dict
-
-    def errors(self):
-        "Returns list of all errors in this collection's formfields"
-        errors = []
-        for field in self.formfield_dict.values():
-            if hasattr(field, 'errors'):
-                errors.extend(field.errors())
-        return errors
-
-    def has_errors(self):
-        return bool(len(self.errors()))
-
-    def html_combined_error_list(self):
-        return ''.join([field.html_error_list() for field in self.formfield_dict.values() if hasattr(field, 'errors')])
-
-class InlineObjectCollection(object):
-    "An object that acts like a sparse list of form field collections."
-    def __init__(self, parent_manipulator, rel_obj, data, errors):
-        self.parent_manipulator = parent_manipulator
-        self.rel_obj = rel_obj
-        self.data = data
-        self.errors = errors
-        self._collections = None
-        self.name = rel_obj.name
-
-    def __len__(self):
-        self.fill()
-        return self._collections.__len__()
-
-    def __getitem__(self, k):
-        self.fill()
-        return self._collections.__getitem__(k)
-
-    def __setitem__(self, k, v):
-        self.fill()
-        return self._collections.__setitem__(k,v)
-
-    def __delitem__(self, k):
-        self.fill()
-        return self._collections.__delitem__(k)
-
-    def __iter__(self):
-        self.fill()
-        return iter(self._collections.values())
-
-    def items(self):
-        self.fill()
-        return self._collections.items()
-
-    def fill(self):
-        if self._collections:
-            return
-        else:
-            var_name = self.rel_obj.opts.object_name.lower()
-            collections = {}
-            orig = None
-            if hasattr(self.parent_manipulator, 'original_object'):
-                orig = self.parent_manipulator.original_object
-            orig_list = self.rel_obj.get_list(orig)
-
-            for i, instance in enumerate(orig_list):
-                collection = {'original': instance}
-                for f in self.rel_obj.editable_fields():
-                    for field_name in f.get_manipulator_field_names(''):
-                        full_field_name = '%s.%d.%s' % (var_name, i, field_name)
-                        field = self.parent_manipulator[full_field_name]
-                        data = field.extract_data(self.data)
-                        errors = self.errors.get(full_field_name, [])
-                        collection[field_name] = FormFieldWrapper(field, data, errors)
-                collections[i] = FormFieldCollection(collection)
-            self._collections = collections
-
-
-class FormField(object):
-    """Abstract class representing a form field.
-
-    Classes that extend FormField should define the following attributes:
-        field_name
-            The field's name for use by programs.
-        validator_list
-            A list of validation tests (callback functions) that the data for
-            this field must pass in order to be added or changed.
-        is_required
-            A Boolean. Is it a required field?
-    Subclasses should also implement a render(data) method, which is responsible
-    for rending the form field in XHTML.
-    """
-    def __str__(self):
-        return self.render('')
-
-    def __repr__(self):
-        return 'FormField "%s"' % self.field_name
-
-    def prepare(self, new_data):
-        "Hook for doing something to new_data (in place) before validation."
-        pass
-
-    def html2python(data):
-        "Hook for converting an HTML datatype (e.g. 'on' for checkboxes) to a Python type"
-        return data
-    html2python = staticmethod(html2python)
-
-    def render(self, data):
-        raise NotImplementedError
-
-    def get_member_name(self):
-        if hasattr(self, 'member_name'):
-            return self.member_name
-        else:
-            return self.field_name
-
-    def extract_data(self, data_dict):
-        if hasattr(self, 'requires_data_list') and hasattr(data_dict, 'getlist'):
-            data = data_dict.getlist(self.get_member_name())
-        else:
-            data = data_dict.get(self.get_member_name(), None)
-        if data is None:
-            data = ''
-        return data
-
-    def convert_post_data(self, new_data):
-        name = self.get_member_name()
-        if new_data.has_key(self.field_name):
-            d = new_data.getlist(self.field_name)
-            try:
-                converted_data = [self.__class__.html2python(data) for data in d]
-            except ValueError:
-                converted_data = d
-            new_data.setlist(name, converted_data)
-        else:
-            try:
-                #individual fields deal with None values themselves
-                new_data.setlist(name, [self.__class__.html2python(None)])
-            except EmptyValue:
-                new_data.setlist(name, [])
-
-
-    def run_validator(self, new_data, validator):
-        if self.is_required or new_data.get(self.field_name, False) or hasattr(validator, 'always_test'):
-            if hasattr(self, 'requires_data_list'):
-                validator(new_data.getlist(self.field_name), new_data)
-            else:
-                validator(new_data.get(self.field_name, ''), new_data)
-
-    def get_validation_errors(self, new_data):
-        errors = {}
-        if self.is_required and not new_data.get(self.field_name, False):
-            errors.setdefault(self.field_name, []).append(gettext('This field is required.'))
-            return errors
-        try:
-            for validator in self.validator_list:
-                try:
-                    self.run_validator(new_data, validator)
-                except validators.ValidationError, e:
-                    errors.setdefault(self.field_name, []).extend(e.messages)
-        # If a CriticalValidationError is raised, ignore any other ValidationErrors
-        # for this particular field
-        except validators.CriticalValidationError, e:
-            errors.setdefault(self.field_name, []).extend(e.messages)
-        return errors
-
-    def get_id(self):
-        "Returns the HTML 'id' attribute for this form field."
-        return FORM_FIELD_ID_PREFIX + self.field_name
-
-####################
-# GENERIC WIDGETS  #
-####################
-
-class TextField(FormField):
-    input_type = "text"
-    def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.length, self.maxlength = length, maxlength
-        self.is_required = is_required
-        self.validator_list = [self.isValidLength, self.hasNoNewlines] + validator_list
-        if member_name != None:
-            self.member_name = member_name
-
-    def isValidLength(self, data, form):
-        if data and self.maxlength and len(data.decode(settings.DEFAULT_CHARSET)) > self.maxlength:
-            raise validators.ValidationError, ngettext("Ensure your text is less than %s character.",
-                "Ensure your text is less than %s characters.", self.maxlength) % self.maxlength
-
-    def hasNoNewlines(self, data, form):
-        if data and '\n' in data:
-            raise validators.ValidationError, gettext("Line breaks are not allowed here.")
-
-    def render(self, data):
-        if data is None:
-            data = ''
-        maxlength = ''
-        if self.maxlength:
-            maxlength = 'maxlength="%s" ' % self.maxlength
-        if isinstance(data, unicode):
-            data = data.encode(settings.DEFAULT_CHARSET)
-        return '<input type="%s" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \
-            (self.input_type, self.get_id(), self.__class__.__name__, self.is_required and ' required' or '',
-            self.field_name, self.length, escape(data), maxlength)
-
-    def html2python(data):
-        return data
-    html2python = staticmethod(html2python)
-
-class PasswordField(TextField):
-    input_type = "password"
-
-class LargeTextField(TextField):
-    def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, maxlength=None):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.rows, self.cols, self.is_required = rows, cols, is_required
-        self.validator_list = validator_list[:]
-        if maxlength:
-            self.validator_list.append(self.isValidLength)
-            self.maxlength = maxlength
-
-    def render(self, data):
-        if data is None:
-            data = ''
-        if isinstance(data, unicode):
-            data = data.encode(settings.DEFAULT_CHARSET)
-        return '<textarea id="%s" class="v%s%s" name="%s" rows="%s" cols="%s">%s</textarea>' % \
-            (self.get_id(), self.__class__.__name__, self.is_required and ' required' or '',
-            self.field_name, self.rows, self.cols, escape(data))
-
-class HiddenField(FormField):
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        self.field_name, self.is_required = field_name, is_required
-        self.validator_list = validator_list[:]
-
-    def render(self, data):
-        return '<input type="hidden" id="%s" name="%s" value="%s" />' % \
-            (self.get_id(), self.field_name, escape(data))
-
-class CheckboxField(FormField):
-    def __init__(self, field_name, checked_by_default=False, validator_list=None, is_required=False):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.checked_by_default = checked_by_default
-        self.is_required = is_required
-        self.validator_list = validator_list[:]
-
-    def render(self, data):
-        checked_html = ''
-        if data or (data is '' and self.checked_by_default):
-            checked_html = ' checked="checked"'
-        return '<input type="checkbox" id="%s" class="v%s" name="%s"%s />' % \
-            (self.get_id(), self.__class__.__name__,
-            self.field_name, checked_html)
-
-    def html2python(data):
-        "Convert value from browser ('on' or '') to a Python boolean"
-        if data == 'on':
-            return True
-        return False
-    html2python = staticmethod(html2python)
-
-class SelectField(FormField):
-    def __init__(self, field_name, choices=None, size=1, is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        if choices is None: choices = []
-        self.field_name = field_name
-        # choices is a list of (value, human-readable key) tuples because order matters
-        self.choices, self.size, self.is_required = choices, size, is_required
-        self.validator_list = [self.isValidChoice] + validator_list
-        if member_name != None:
-            self.member_name = member_name
-
-    def render(self, data):
-        output = ['<select id="%s" class="v%s%s" name="%s" size="%s">' % \
-            (self.get_id(), self.__class__.__name__,
-             self.is_required and ' required' or '', self.field_name, self.size)]
-        str_data = str(data) # normalize to string
-        for value, display_name in self.choices:
-            selected_html = ''
-            if str(value) == str_data:
-                selected_html = ' selected="selected"'
-            output.append('    <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(display_name)))
-        output.append('  </select>')
-        return '\n'.join(output)
-
-    def isValidChoice(self, data, form):
-        str_data = str(data)
-        str_choices = [str(item[0]) for item in self.choices]
-        if str_data not in str_choices:
-            raise validators.ValidationError, gettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data': str_data, 'choices': str_choices}
-
-class NullSelectField(SelectField):
-    "This SelectField converts blank fields to None"
-    def html2python(data):
-        if not data:
-            return None
-        return data
-    html2python = staticmethod(html2python)
-
-class RadioSelectField(FormField):
-    def __init__(self, field_name, choices=None, ul_class='', is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        if choices is None: choices = []
-        self.field_name = field_name
-        # choices is a list of (value, human-readable key) tuples because order matters
-        self.choices, self.is_required = choices, is_required
-        self.validator_list = [self.isValidChoice] + validator_list
-        self.ul_class = ul_class
-        if member_name != None:
-            self.member_name = member_name
-
-    def render(self, data):
-        """
-        Returns a special object, RadioFieldRenderer, that is iterable *and*
-        has a default str() rendered output.
-
-        This allows for flexible use in templates. You can just use the default
-        rendering:
-
-            {{ field_name }}
-
-        ...which will output the radio buttons in an unordered list.
-        Or, you can manually traverse each radio option for special layout:
-
-            {% for option in field_name.field_list %}
-                {{ option.field }} {{ option.label }}<br />
-            {% endfor %}
-        """
-        class RadioFieldRenderer:
-            def __init__(self, datalist, ul_class):
-                self.datalist, self.ul_class = datalist, ul_class
-            def __str__(self):
-                "Default str() output for this radio field -- a <ul>"
-                output = ['<ul%s>' % (self.ul_class and ' class="%s"' % self.ul_class or '')]
-                output.extend(['<li>%s %s</li>' % (d['field'], d['label']) for d in self.datalist])
-                output.append('</ul>')
-                return ''.join(output)
-            def __iter__(self):
-                for d in self.datalist:
-                    yield d
-            def __len__(self):
-                return len(self.datalist)
-        datalist = []
-        str_data = str(data) # normalize to string
-        for i, (value, display_name) in enumerate(self.choices):
-            selected_html = ''
-            if str(value) == str_data:
-                selected_html = ' checked="checked"'
-            datalist.append({
-                'value': value,
-                'name': display_name,
-                'field': '<input type="radio" id="%s" name="%s" value="%s"%s/>' % \
-                    (self.get_id() + '_' + str(i), self.field_name, value, selected_html),
-                'label': '<label for="%s">%s</label>' % \
-                    (self.get_id() + '_' + str(i), display_name),
-            })
-        return RadioFieldRenderer(datalist, self.ul_class)
-
-    def isValidChoice(self, data, form):
-        str_data = str(data)
-        str_choices = [str(item[0]) for item in self.choices]
-        if str_data not in str_choices:
-            raise validators.ValidationError, gettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':str_data, 'choices':str_choices}
-
-class NullBooleanField(SelectField):
-    "This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None"
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        SelectField.__init__(self, field_name, choices=[('1', 'Unknown'), ('2', 'Yes'), ('3', 'No')],
-            is_required=is_required, validator_list=validator_list)
-
-    def render(self, data):
-        if data is None: data = '1'
-        elif data == True: data = '2'
-        elif data == False: data = '3'
-        return SelectField.render(self, data)
-
-    def html2python(data):
-        return {None: None, '1': None, '2': True, '3': False}[data]
-    html2python = staticmethod(html2python)
-
-class SelectMultipleField(SelectField):
-    requires_data_list = True
-    def render(self, data):
-        output = ['<select id="%s" class="v%s%s" name="%s" size="%s" multiple="multiple">' % \
-            (self.get_id(), self.__class__.__name__, self.is_required and ' required' or '',
-            self.field_name, self.size)]
-        str_data_list = map(str, data) # normalize to strings
-        for value, choice in self.choices:
-            selected_html = ''
-            if str(value) in str_data_list:
-                selected_html = ' selected="selected"'
-            output.append('    <option value="%s"%s>%s</option>' % (escape(value), selected_html, escape(choice)))
-        output.append('  </select>')
-        return '\n'.join(output)
-
-    def isValidChoice(self, field_data, all_data):
-        # data is something like ['1', '2', '3']
-        str_choices = [str(item[0]) for item in self.choices]
-        for val in map(str, field_data):
-            if val not in str_choices:
-                raise validators.ValidationError, gettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':val, 'choices':str_choices}
-
-    def html2python(data):
-        if data is None:
-            raise EmptyValue
-        return data
-    html2python = staticmethod(html2python)
-
-class CheckboxSelectMultipleField(SelectMultipleField):
-    """
-    This has an identical interface to SelectMultipleField, except the rendered
-    widget is different. Instead of a <select multiple>, this widget outputs a
-    <ul> of <input type="checkbox">es.
-
-    Of course, that results in multiple form elements for the same "single"
-    field, so this class's prepare() method flattens the split data elements
-    back into the single list that validators, renderers and save() expect.
-    """
-    requires_data_list = True
-    def __init__(self, field_name, choices=None, ul_class='', validator_list=None):
-        if validator_list is None: validator_list = []
-        if choices is None: choices = []
-        self.ul_class = ul_class
-        SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
-
-    def prepare(self, new_data):
-        # new_data has "split" this field into several fields, so flatten it
-        # back into a single list.
-        data_list = []
-        for value, readable_value in self.choices:
-            if new_data.get('%s%s' % (self.field_name, value), '') == 'on':
-                data_list.append(value)
-        new_data.setlist(self.field_name, data_list)
-
-    def render(self, data):
-        output = ['<ul%s>' % (self.ul_class and ' class="%s"' % self.ul_class or '')]
-        str_data_list = map(str, data) # normalize to strings
-        for value, choice in self.choices:
-            checked_html = ''
-            if str(value) in str_data_list:
-                checked_html = ' checked="checked"'
-            field_name = '%s%s' % (self.field_name, value)
-            output.append('<li><input type="checkbox" id="%s" class="v%s" name="%s"%s value="on" /> <label for="%s">%s</label></li>' % \
-                (self.get_id() + escape(value), self.__class__.__name__, field_name, checked_html,
-                self.get_id() + escape(value), choice))
-        output.append('</ul>')
-        return '\n'.join(output)
-
-####################
-# FILE UPLOADS     #
-####################
-
-class FileUploadField(FormField):
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        self.field_name, self.is_required = field_name, is_required
-        self.validator_list = [self.isNonEmptyFile] + validator_list
-
-    def isNonEmptyFile(self, field_data, all_data):
-        try:
-            content = field_data['content']
-        except TypeError:
-            raise validators.CriticalValidationError, gettext("No file was submitted. Check the encoding type on the form.")
-        if not content:
-            raise validators.CriticalValidationError, gettext("The submitted file is empty.")
-
-    def render(self, data):
-        return '<input type="file" id="%s" class="v%s" name="%s" />' % \
-            (self.get_id(), self.__class__.__name__, self.field_name)
-
-    def html2python(data):
-        if data is None:
-            raise EmptyValue
-        return data
-    html2python = staticmethod(html2python)
-
-class ImageUploadField(FileUploadField):
-    "A FileUploadField that raises CriticalValidationError if the uploaded file isn't an image."
-    def __init__(self, *args, **kwargs):
-        FileUploadField.__init__(self, *args, **kwargs)
-        self.validator_list.insert(0, self.isValidImage)
-
-    def isValidImage(self, field_data, all_data):
-        try:
-            validators.isValidImage(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-####################
-# INTEGERS/FLOATS  #
-####################
-
-class IntegerField(TextField):
-    def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None, member_name=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isInteger] + validator_list
-        if member_name is not None:
-            self.member_name = member_name
-        TextField.__init__(self, field_name, length, maxlength, is_required, validator_list)
-
-    def isInteger(self, field_data, all_data):
-        try:
-            validators.isInteger(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        if data == '' or data is None:
-            return None
-        return int(data)
-    html2python = staticmethod(html2python)
-
-class SmallIntegerField(IntegerField):
-    def __init__(self, field_name, length=5, maxlength=5, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isSmallInteger] + validator_list
-        IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
-
-    def isSmallInteger(self, field_data, all_data):
-        if not -32768 <= int(field_data) <= 32767:
-            raise validators.CriticalValidationError, gettext("Enter a whole number between -32,768 and 32,767.")
-
-class PositiveIntegerField(IntegerField):
-    def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isPositive] + validator_list
-        IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
-
-    def isPositive(self, field_data, all_data):
-        if int(field_data) < 0:
-            raise validators.CriticalValidationError, gettext("Enter a positive number.")
-
-class PositiveSmallIntegerField(IntegerField):
-    def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isPositiveSmall] + validator_list
-        IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
-
-    def isPositiveSmall(self, field_data, all_data):
-        if not 0 <= int(field_data) <= 32767:
-            raise validators.CriticalValidationError, gettext("Enter a whole number between 0 and 32,767.")
-
-class FloatField(TextField):
-    def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        self.max_digits, self.decimal_places = max_digits, decimal_places
-        validator_list = [self.isValidFloat] + validator_list
-        TextField.__init__(self, field_name, max_digits+2, max_digits+2, is_required, validator_list)
-
-    def isValidFloat(self, field_data, all_data):
-        v = validators.IsValidFloat(self.max_digits, self.decimal_places)
-        try:
-            v(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        if data == '' or data is None:
-            return None
-        return float(data)
-    html2python = staticmethod(html2python)
-
-####################
-# DATES AND TIMES  #
-####################
-
-class DatetimeField(TextField):
-    """A FormField that automatically converts its data to a datetime.datetime object.
-    The data should be in the format YYYY-MM-DD HH:MM:SS."""
-    def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        self.field_name = field_name
-        self.length, self.maxlength = length, maxlength
-        self.is_required = is_required
-        self.validator_list = [validators.isValidANSIDatetime] + validator_list
-
-    def html2python(data):
-        "Converts the field into a datetime.datetime object"
-        import datetime
-        try:
-            date, time = data.split()
-            y, m, d = date.split('-')
-            timebits = time.split(':')
-            h, mn = timebits[:2]
-            if len(timebits) > 2:
-                s = int(timebits[2])
-            else:
-                s = 0
-            return datetime.datetime(int(y), int(m), int(d), int(h), int(mn), s)
-        except ValueError:
-            return None
-    html2python = staticmethod(html2python)
-
-class DateField(TextField):
-    """A FormField that automatically converts its data to a datetime.date object.
-    The data should be in the format YYYY-MM-DD."""
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidDate] + validator_list
-        TextField.__init__(self, field_name, length=10, maxlength=10,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidDate(self, field_data, all_data):
-        try:
-            validators.isValidANSIDate(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        "Converts the field into a datetime.date object"
-        import time, datetime
-        try:
-            time_tuple = time.strptime(data, '%Y-%m-%d')
-            return datetime.date(*time_tuple[0:3])
-        except (ValueError, TypeError):
-            return None
-    html2python = staticmethod(html2python)
-
-class TimeField(TextField):
-    """A FormField that automatically converts its data to a datetime.time object.
-    The data should be in the format HH:MM:SS or HH:MM:SS.mmmmmm."""
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidTime] + validator_list
-        TextField.__init__(self, field_name, length=8, maxlength=8,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidTime(self, field_data, all_data):
-        try:
-            validators.isValidANSITime(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        "Converts the field into a datetime.time object"
-        import time, datetime
-        try:
-            part_list = data.split('.')
-            try:
-                time_tuple = time.strptime(part_list[0], '%H:%M:%S')
-            except ValueError: # seconds weren't provided
-                time_tuple = time.strptime(part_list[0], '%H:%M')
-            t = datetime.time(*time_tuple[3:6])
-            if (len(part_list) == 2):
-                t = t.replace(microsecond=int(part_list[1]))
-            return t
-        except (ValueError, TypeError, AttributeError):
-            return None
-    html2python = staticmethod(html2python)
-
-####################
-# INTERNET-RELATED #
-####################
-
-class EmailField(TextField):
-    "A convenience FormField for validating e-mail addresses"
-    def __init__(self, field_name, length=50, maxlength=75, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidEmail] + validator_list
-        TextField.__init__(self, field_name, length, maxlength=maxlength,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidEmail(self, field_data, all_data):
-        try:
-            validators.isValidEmail(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-class URLField(TextField):
-    "A convenience FormField for validating URLs"
-    def __init__(self, field_name, length=50, maxlength=200, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidURL] + validator_list
-        TextField.__init__(self, field_name, length=length, maxlength=maxlength,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidURL(self, field_data, all_data):
-        try:
-            validators.isValidURL(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-class IPAddressField(TextField):
-    def __init__(self, field_name, length=15, maxlength=15, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidIPAddress] + validator_list
-        TextField.__init__(self, field_name, length=length, maxlength=maxlength,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidIPAddress(self, field_data, all_data):
-        try:
-            validators.isValidIPAddress4(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        return data or None
-    html2python = staticmethod(html2python)
-
-####################
-# MISCELLANEOUS    #
-####################
-
-class FilePathField(SelectField):
-    "A SelectField whose choices are the files in a given directory."
-    def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None):
-        import os
-        from django.db.models import BLANK_CHOICE_DASH
-        if match is not None:
-            import re
-            match_re = re.compile(match)
-        choices = not is_required and BLANK_CHOICE_DASH[:] or []
-        if recursive:
-            for root, dirs, files in os.walk(path):
-                for f in files:
-                    if match is None or match_re.search(f):
-                        choices.append((os.path.join(root, f), f))
-        else:
-            try:
-                for f in os.listdir(path):
-                    full_file = os.path.join(path, f)
-                    if os.path.isfile(full_file) and (match is None or match_re.search(f)):
-                        choices.append((full_file, f))
-            except OSError:
-                pass
-        SelectField.__init__(self, field_name, choices, 1, is_required, validator_list)
-
-class PhoneNumberField(TextField):
-    "A convenience FormField for validating phone numbers (e.g. '630-555-1234')"
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidPhone] + validator_list
-        TextField.__init__(self, field_name, length=12, maxlength=12,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidPhone(self, field_data, all_data):
-        try:
-            validators.isValidPhone(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-class USStateField(TextField):
-    "A convenience FormField for validating U.S. states (e.g. 'IL')"
-    def __init__(self, field_name, is_required=False, validator_list=None):
-        if validator_list is None: validator_list = []
-        validator_list = [self.isValidUSState] + validator_list
-        TextField.__init__(self, field_name, length=2, maxlength=2,
-            is_required=is_required, validator_list=validator_list)
-
-    def isValidUSState(self, field_data, all_data):
-        try:
-            validators.isValidUSState(field_data, all_data)
-        except validators.ValidationError, e:
-            raise validators.CriticalValidationError, e.messages
-
-    def html2python(data):
-        return data.upper() # Should always be stored in upper case
-    html2python = staticmethod(html2python)
-