formencode模式动态添加字段

3 投票
1 回答
1100 浏览
提问于 2025-04-16 21:59

我们来举个例子,假设有一个用户的 Schema,网站管理员可以设置需要的电话号码数量:

class MySchema(Schema):
    name = validators.String(not_empty=True)
    phone_1 = validators.PhoneNumber(not_empty=True)
    phone_2 = validators.PhoneNumber(not_empty=True)
    phone_3 = validators.PhoneNumber(not_empty=True)
    ...

我原本以为可以简单地这样做:

class MySchema(Schema):
    name = validators.String(not_empty=True)
    def __init__(self, *args, **kwargs):
        requested_phone_numbers = Session.query(...).scalar()
        for n in xrange(requested_phone_numbers):
            key = 'phone_{0}'.format(n)
            kwargs[key] = validators.PhoneNumber(not_empty=True)
        Schema.__init__(self, *args, **kwargs)

因为我在 FormEncode 的文档中看到:

验证器使用实例变量来存储它们的自定义信息。你可以通过子类化或者正常实例化来设置这些。

而且文档中提到 Schema 是一个复合验证器,它是 FancyValidator 的子类,所以我猜这样做是对的。

但是这样并没有成功:我简单添加的 phone_n 被忽略了,只有 name 是必填的。

更新:

我还尝试了重写 __new____classinit__,但在提问之前都没有成功……

1 个回答

5

我也遇到过同样的问题,后来在这里找到了解决办法:http://markmail.org/message/m5ckyaml36eg2w3m

关键是要在你的init方法中使用schema的add_field方法。

class MySchema(Schema):
    name = validators.String(not_empty=True)

    def __init__(self, *args, **kwargs):
        requested_phone_numbers = Session.query(...).scalar()
        for n in xrange(requested_phone_numbers):
            key = 'phone_{0}'.format(n)
            self.add_field(key, validators.PhoneNumber(not_empty=True))

我觉得没必要调用父类的init。

撰写回答