0

所以基本上我想尝试清理/过滤或清理类似于其他 python web 框架的输入表单。具体来说,我试图从电子邮件地址中删除空格。我可以在 javascript 中做到这一点,但似乎应该有一种方法可以使用 zope 库来做到这一点。

该文档详细介绍了设置约束,但实际上并未涉及修改表单值。当然,问题是在我可以对空白做任何事情之前触发约束异常。

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
4

3 回答 3

2

有几种不同的可能方法,具体取决于您要放置抽象层的位置。

如果您想让它相对接近数据模型,您可以在自定义字段上定义一个set方法,如下所示:

    def set(self, obj, value):
        if value is not None:
            value = value.strip()
        super().set(obj, value)

这意味着任何通过模式设置字段的东西(可能是某种 API?)都会去除空格。这种方法通常用于类型转换,但将其用于这种简单的规范化似乎也不是太不合理。

如果您希望空格剥离成为表单视图的属性,但仍允许合理数量的代码重用,那么您可以使用自定义小部件,如您在自己的答案中建议的那样。

最后,如果您只是想拥有特定于特定表单的一些自定义行为,那么您总是可以让表单在从小部件读取数据并将其应用于底层模型之间手动处理数据,可能使用动作验证器,甚至如果您使用zope.formlib的是直接调用的“编辑表单”方法,则更明确form.getWidgetsDataform.applyChanges

于 2022-01-07T11:25:17.600 回答
0

我最终使用自定义小部件功能进行了以下操作:

class StripTextWidget(zope.formlib.textwidgets.TextWidget):
    def _getFormInput(self):
        value = super(StripTextWidget, self)._getFormInput()
        return value.strip()

...
def fields(self):
   """Build form fields dynamically"""
   fields = Fields(IPerson).select("name", "email")
   fields["email"].custom_widget = StripTextWidget

这种方式也在本书第 130 页的使用 Zope 3 的 Web 组件开发中进行了描述

于 2021-12-09T23:36:11.767 回答
0

实际上我最终这样做了,因为它比我原来的做法更通用,它涉及单独设置每个字段而不是全局选项。

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)
于 2022-01-14T16:28:20.457 回答