Search code examples
pythonformsvalidationplonezope3

Modify or clean form input in zope or plone


So basically I'd like to try to clean/filter or sanitize an input form similar to other python web frameworks. Specifically I am trying to strip whitespace from the email address. I can do it in javascript but it seems like there should be a way to do it using the zope libraries.

The documentation goes into detail on setting up the constraints but not actually on modifying form values. Of course the issue is the constraint exception gets triggered before I can do anything to the whitespace.

class IEmailAddress(zope.schema.interfaces.ITextLine):
    pass

class InvalidEmailAddress(zope.schema.ValidationError):
    def __init__(self, email):
        super(InvalidEmailAddress, self).__init__(
            "'%s' is not a valid e-mail address." % email)


class EmailAddress(zope.schema.TextLine):

    zope.interface.implements(IEmailAddress)

    def constraint(self, value):
        return '\n' not in value and '\r' not in value

    def _validate(self, value):
        super(EmailAddress, self)._validate(value)
        if not is_email_address(value):
            raise InvalidEmailAddress(value)


class InviteForm(FormProvider):

    dropdown_css_class = "dropdown-spacer-left"

    def fields(self):
        """Build form fields dynamically"""
        fields = Fields(IPerson).select("name", "email")
        person = self.request.principal.person

        field['email'].field.strip() # Does not work

    @action("Invite", primary=True)
    def add_administrator(self, action, data):
        name, email = data["name"], data["email"]

        email = email.strip() # Does not work

Solution

  • I actually ended up doing it this way because it was more general than the original way I was doing it, which involved setting each field individually instead of a global option.

    class StripTextWidget(zope.formlib.textwidgets.TextWidget):
        def _getFormInput(self):
            value = super(StripTextWidget, self)._getFormInput()
            return value.strip()
    
    class EmailAddress(zope.schema.TextLine):
    
        zope.interface.implements(IEmailAddress)
        custom_widget = StripTextWidget
    
        def constraint(self, value):
            return '\n' not in value and '\r' not in value
    
        def _validate(self, value):
            super(EmailAddress, self)._validate(value)
            if not is_email_address(value):
                raise InvalidEmailAddress(value)