【问题标题】:Modify or clean form input in zope or plone修改或清理 zope 或 plone 中的表单输入
【发布时间】:2022-01-14 18:22:35
【问题描述】:

所以基本上我想尝试清理/过滤或清理类似于其他 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

【问题讨论】:

    标签: python forms validation plone zope3


    【解决方案1】:

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

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

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

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

    如果您希望空白剥离成为表单视图的属性,但仍允许合理数量的代码重用,那么您可以按照your own answer 中的建议使用自定义小部件。

    最后,如果您只是想拥有一些特定于特定表单的自定义行为,那么您总是可以让表单在从小部件读取数据并将其应用到底层模型之间手动处理数据,也许使用@987654323 @,或者如果您使用zope.formlibEdit Forms 方法,您可以直接调用form.getWidgetsDataform.applyChanges,甚至更明确。

    【讨论】:

    • set() 有效,但在我的情况下无效,因为有一个 constraintset() 之前引发异常。我最终修改了custom_widget,而不是在全局范围内调用,我没有意识到可以这样做。
    【解决方案2】:

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

    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 组件开发也描述了这种方式

    【讨论】:

      【解决方案3】:

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

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多