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

发布于 2024-08-05 15:28:34 字数 1797 浏览 4 评论 0原文

我对 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 列。您只能添加必需的列,而不能删除它。 ",但我想允许非 NULL 空字符串,这是 validators.required 不允许的。 Django 中有类似 blank=True, null=False 的东西吗?

更准确地说,我想要一个像下面这样的自定义验证器,要么允许带有 type=None 的空字符串,要么将所有值设置为非 NULL 和非空:

# 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 ,因为它似乎也不是正确的解决方案。

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

羁〃客ぐ 2024-08-12 15:28:34

终于找到了一个拼凑的办法,但似乎这是唯一明智的方法:

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

对于验证器函数,当值为 None 时,FA 将完全跳过所有验证,因为按照惯例,它不会将 None 传递给验证器(除非设置 validators.required ,这是硬编码的)。我已提交增强请求票据,试图解决此问题。

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.

迷你仙 2024-08-12 15:28:34

您能解释一下为什么 nullable=True 不是解决方案吗?

对我来说,在数据库中存储空字符串似乎毫无用处,我不鼓励这样做。如果没有数据,则选择更有效的数据库类型。

我个人认为 Django 对于字符串的解决方案是错误的,因为它并不真正支持 CharFields 中的 NULL。如果您想将 NULL 存储在 CharField 中,则必须在代码中手动执行此操作。

Can you explain why nullable=True would not be the solution?

To me it seems useless to store empty strings in the database and I would not encourage it. If there is no data than choose the more efficient type for the database.

Personally I think the Django solution in case of strings is wrong since it does not really support NULL in CharFields. If you want to store NULL in a CharField you will have to do it manually in the code.

你的往事 2024-08-12 15:28:34

这与我遇到的问题完全相同,我经常为现有数据库编写接口并希望使用形式化学,但最终不得不手动删除“必需性”,因为我无法更改数据库。

This is exactly the same issue i'm having, where I often write interfaces for existing databases and want to use formalchemy but end up having to manually remove 'requiredness' as I am not able to change the database.

歌枕肩 2024-08-12 15:28:34

您可以通过更改 null_as 列属性来教导 FormAlchemy 不要将空输入替换为 None。

 whatever = Column(Unicode(999), required=False, null_as=("","\0"), nullable=False, default="", doc="Whatever for ever")

Formalchemy 会将等于 null_as 元组第二个成员的输入替换为 None。 (第一个是 SELECT 和类似字段的显示文本。)

如果将其设置为用户无法输入的字符串,则这种情况永远不会发生。

You can teach FormAlchemy to not replace an empty input with None by changing the null_as column attribute.

 whatever = Column(Unicode(999), required=False, null_as=("","\0"), nullable=False, default="", doc="Whatever for ever")

Formalchemy will replace input that's equal to the second member of the null_as tuple with None. (The first is the display text for SELECTs and similar fields.)

If you set that to a string the user cannot input, this will never happen.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文