在FormAlchemy中不要求非NULL字段(允许空字符串)

3 投票
4 回答
3002 浏览
提问于 2025-04-15 14:30

我对FormAlchemy还比较陌生,似乎有些地方没弄明白。我定义了一个SQLAlchemy模型,代码如下:

...
class Device(meta.Base):
    __tablename__ = 'devices'

    id = sa.Column('id_device', sa.types.Integer, primary_key=True)
    serial_number = sa.Column('sn', sa.types.Unicode(length=20), nullable=False)
    mac = sa.Column('mac', sa.types.Unicode(length=12), nullable=False)
    ipv4 = sa.Column('ip', sa.types.Unicode(length=15), nullable=False)
    type_id = sa.Column('type_id', sa.types.Integer,
                        sa.schema.ForeignKey('device_types.id'))
    type = orm.relation(DeviceType, primaryjoin=type_id == DeviceType.id)
...

然后在我的(Pylons)控制器中,我这样创建了一个FormAlchemy表单:

c.device = model.meta.Session.query(model.Device).get(device_id)
fs = FieldSet(c.device, data=request.POST or None)
fs.configure(options=[fs.ipv4.label(u'IP').readonly(),
                      fs.type.label(u'Type').with_null_as((u'—', '')),
                      fs.serial_number.label(u'S/N'),
                      fs.mac.label(u'MAC')])

文档上说“默认情况下,NOT NULL列是必填的。你只能添加必填项,不能去掉它。”但我想允许非空的空字符串,而validators.required是不允许的。有没有类似于Django中的blank=True, null=False的设置呢?

更具体地说,我想要一个自定义的验证器,像下面这样,要么允许空字符串并设置type=None,要么所有值都设置为非空且非空字符串:

# For use on fs.mac and fs.serial_number.
# I haven't tested this code yet.
def required_when_type_is_set(value, field):
    type_is_set = field.parent.type.value is not None:
    if value is None or (type_is_set and value.strip() = ''):
        raise validators.ValidationError(u'Please enter a value')

如果可以的话,我希望不去修改formalchemy.validators.required或其他临时解决方案。我也不想在模型字段上设置nullable=True,因为这似乎也不是个合适的解决办法。

在这种情况下,正确的表单验证方法是什么呢?提前感谢任何建议。

4 个回答

0

我遇到的情况和这个完全一样,我经常需要为现有的数据库写接口,想用formalchemy,但最后不得不手动去掉“必填”的设置,因为我无法更改数据库。

3

你能解释一下为什么 nullable=True 可能不是解决办法吗?

在我看来,把空字符串存储在数据库里是没什么用的,我也不推荐这样做。如果没有数据的话,应该选择更有效的数据库类型。

我个人觉得在处理字符串时,Django 的解决方案是不太对的,因为它并不真正支持 CharFields 中的 NULL 值。如果你想在 CharField 中存储 NULL 值,就得在代码里手动处理。

4

最后找到了一种权宜之计,但似乎这是唯一合理的做法:

  fs.serial_number.validators.remove(formalchemy.validators.required)
  fs.mac.validators.remove(formalchemy.validators.required)

对于验证器函数,当值为 None 时,FA 会 完全 跳过所有的验证,因为按照惯例,它不会把 None 传给验证器(除了在设置了 validators.required 的情况下,这个是硬编码的)。我已经提交了一个增强请求,试图解决这个问题,具体可以查看这个 链接

撰写回答