diff --git a/c3l_membership/forms.py b/c3l_membership/forms.py --- a/c3l_membership/forms.py +++ b/c3l_membership/forms.py @@ -2,10 +2,55 @@ from datetime import date from flask_babel import lazy_gettext from flask_wtf import FlaskForm -from wtforms import BooleanField, DateField, RadioField, StringField, SubmitField +from wtforms import ( + BooleanField, + DateField, + RadioField, + StringField, + SubmitField, + ValidationError, +) from wtforms.validators import Email, InputRequired, Length, Optional +class NotEqualTo: + """ + Compares the values of two fields. + :param fieldname: + The name of the other field to compare to. + :param message: + Error message to raise in case of a validation error. Can be + interpolated with `%(other_label)s` and `%(other_name)s` to provide a + more helpful error. + """ + + def __init__(self, fieldname, message=None): + self.fieldname = fieldname + self.message = message + + def __call__(self, form, field): + try: + other = form[self.fieldname] + except KeyError as exc: + raise ValidationError( + field.gettext("Invalid field name '%s'.") % self.fieldname + ) from exc + if field.data != other.data: + return + + d = { + "other_label": hasattr(other, "label") + and other.label.text + or self.fieldname, + "other_name": self.fieldname, + } + message = self.message + if message is None: + message = field.gettext("Field must not be equal to %(other_name)s.") + + raise ValidationError(message % d) + + class MembershipForm(FlaskForm): username = StringField( @@ -50,6 +95,15 @@ class MembershipForm(FlaskForm): lazy_gettext( "I am a student and would like to have the reduced membership fees." ), + validators=[ + Optional(), + NotEqualTo( + "starving", + lazy_gettext( + "Student and Starving Hacker are mutually exclusive! Please select only one of them." + ), + ), + ], ) starving = BooleanField( diff --git a/c3l_membership/views.py b/c3l_membership/views.py --- a/c3l_membership/views.py +++ b/c3l_membership/views.py @@ -97,16 +97,19 @@ def index(): else date(9999, 12, 12), "username": form.username.data, "email": form.email.data, - "address": " ".join( - ( - form.street.data, - form.zip.data, - form.city.data, - form.state.data, - form.country.data, - ) + "address": re.sub( + "\s+", + " ", + " ".join( + ( + form.street.data, + form.zip.data, + form.city.data, + form.state.data, + form.country.data, + ) + ), ), - "address": re.sub("\s+", " ", xml_data["address"]), "voting": 1 if form.membership.data == "regular" else 0, "date": now, }