The purpose of web development frameworks is to make common web
development tasks easier, or give them to you for free.  A forms
framework which requires custom code for password comparisons does not
satisfy this fundamental requirement.

I've seen the test codes that tell you how to compare multiple fields
by creating custom clean methods.  Why should one have to do that
every time you need to compare fields?  It's a consequence of
Newforms' architecture, and I think it should be changed.

>From my inspection of the code, the architecture is as follows:
Forms have fields, and forms have data.  When a form has fields /and/
data, it also has BoundFields, special little objects that have access
to both the field information and the data.

This means that the field itself has no access to the data, or to the
form, or to itself, which in turn means that common operations that
require access to form data cannot be done from within the Field,
which I feel is the proper place to put it to ensure reusability.

What's wrong with modifying the Newforms architecture to enable fields
to have access to form data?  There are many ways of doing this, but
I've implemented a naive method as below:

class AwareForm(forms.Form):
    """
    This behaves as a regular form, except it makes all fields aware
of their
    corresponding forms.BoundField object through a bound_field
attribute.
    """
    def is_valid(self):
        for bound_field in self:
            bound_field.field.bound_field = bound_field
        return forms.Form.is_valid(self)

This form enables fields to do all sorts of fun tricks, like the
following example that could work for Password confirmation (warning,
following example is not as DRY as it could be):

class ConfirmCharField(forms.CharField):
    """
    This field behaves exactly the same as the CharField that is given
    to the constructor as the field parameter, and it also validates
    that it matches the value of the field with the same name as this
    field minus "confirm_"

    This field must be named "confirm_<field>", where <field> is the
name
    of the field to confirm.

    Since this relies on the name of the field and on the form data,
this
    must be in an AwareForm.
    """
    def __init__(self, field, error=u'This field must match the %s
field.'):
        self.field = field
        self.error = error
        super(ConfirmCharField,
self).__init__(max_length=field.max_length,
 
min_length=field.min_length,
 
required=field.required,
                                               widget=field.widget,
                                               label=field.label,
                                               initial=field.initial,
 
help_text=field.help_text)

    def clean(self, value):
        "Validates that this field's value is the same as the field to
confirm against"
        super(ConfirmCharField, self).clean(value)
        name = self.bound_field.name.replace('confirm_','')
        if value != self.bound_field.form[name].data:
            raise ValidationError(self.error)
        return value

and this next example, which could work for unique username
validation.

class UniqueCharField(forms.CharField):
    """
    This field behaves exactly the same as a CharField, except that it
also
    validates that an object does not already exist in the database

    Since this relies on the name of the field, this must be in an
AwareForm.
    """
    def __init__(self, cls, error=u'This field must be unique.',
*args, **kwargs):
        self.cls = cls
        self.error = error
        super(UniqueCharField, self).__init__(*args, **kwargs)

    def clean(self, value):
        """
        Validates that this field's value does not already exist in
the database
        for the given type
        """
        super(UniqueCharField, self).clean(value)
        column = self.bound_field.name
        if len(self.cls.objects.extra(where=[column+'=\''+value
+'\''])) != 0:
            raise ValidationError(self.error)
        return value

Then you could have a form to, say, register a new user:

class JoinForm(AwareForm):
    """
    This is the form that prospective members use to sign up to the
site
    """
    username = UniqueCharField(cls=User, error="Another user has this
username")
    email = forms.EmailField()
    password =
forms.CharField(widget=PasswordInput(render_value=False))
    confirm_password = ConfirmCharField(field=password, error="The
passwords must match")

Anyone have any thoughts?

Thanks,
Ian


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to