Do not require non-NULL field (allow empty strings) in FormAlchemy

formalchemy, pylons, python, sqlalchemy, validation

Solution

Finally found a kludge, but it seems this is the only sane way to do it:

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

For the validator function, that FA will completely skip all validation when the value is `None`, because, by convention, it won't pass `None` to validators (except for when `validators.required` is set, which is hard-coded). I've filed an enhancement request ticket trying to solve this.

Problem

I'm fairly novice to FormAlchemy and it seems that I don't get something. I have a SQLAlchemy model defined like this: ``` ... 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) ... ``` Then in my (Pylons) controller I create a FormAlchemy form like this: ``` 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')]) ``` The documentation says that "By default, NOT NULL columns are required. You can only add required-ness, not remove it.", but I want to allow non-NULL empty strings, which `validators.required` disallows. Is there something like `blank=True, null=False` in Django? To be more precise, I want a custom validator like one below, to either allow empty strings with `type=None` or all values to be set non-NULL and non-empty: ``` # 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') ``` If possible, I'd like to refrain from monkey-patching `formalchemy.validators.required` or other kludges. I don't want to set `nullable=True` on model fields, because it doesn't seems to be proper solution too. What's the correct way to validate form in such case? Thanks for any suggestions in advance.

Original source

Related problems