2012-06-29 44 views
2

我看到很多应用程序使用Form对象来验证数据,然后将数据传递给模型,同时在模型中完全不验证。我觉得最好将模型本身的核心验证(例如,没有18岁以下的用户)放在不管上下文的情况下运行。换句话说,我不在乎用户是如何创建的(无论是通过web ui还是命令行),核心规则应该始终适用。我想使用SQLAlchemy(在金字塔应用程序中),我想以我的表单(WTForms)始终尊重模型中定义的核心规则的方式在模型中定义我的核心验证规则,以便所有数据是一致的。如何使用SQLAlchemy在模型中进行表单验证?

其他人已经在做这个或类似的东西吗?

this php类似的解决方案。

+0

难道你不能重写你在模型类中使用你的模型的get/put/save/create方法吗(因为它们应该总是优先),那么就用'super'来做实际的创建/更新如果它通过测试? –

+1

为什么不在模型中进行验证的原因之一是您可能有不同的形式。一个有趣的例子是保存一个不完整的模型。如果您尝试保存不完整的模型,那么您的模型验证将失败,但是如果您在表单中进行了验证。一种形式可能会失败或通过,但最终结果总是有效的。在模型中进行验证会使您执行一些丑陋的事情,例如条件验证......请记住,模型不应该包含任何逻辑。 –

+0

@LoïcFaure-Lacroix非常好的一点,但我只考虑核心规则,这可以防止保存不完整/损坏的模型。例如,“数据库中的每个用户必须具有有效年龄,没有例外”。我觉得像这样重要的规则应该存在于模型中,如果你愿意的话,它可以作为最后的防御墙。 – BDuelz

回答

2

SQLAlchemy允许您注册侦听器,当发生某些事件时会调用这些侦听器,例如,您可以注册在模型字段被修改时要触发的事件。从SQLAlchemy documentation

听众必须返回 值的可能修改的版本的选项,当RETVAL = True标志被传递给听():

def validate_phone(target, value, oldvalue, initiator): 
    "Strip non-numeric characters from a phone number" 

    return re.sub(r'(?![0-9])', '', value) 

# setup listener on UserContact.phone attribute, instructing 
# it to use the return value 
listen(UserContact.phone, 'set', validate_phone, retval=True) 

甲验证函数像上述也可以提起例外 作为ValueError停止操作。

因此,如您所见,您可以在模型级别修改或拒绝特定字段的值。

我不确定您的表单库是否与此功能集成,但它绝对不应该太难以推出您自己的解决方案。

+2

[@validates](http://docs.sqlalchemy.org/en/rel_0_9/orm/mapper_config.html#simple-validators)呢? – Zitrax

+0

@Zitrak:链接已更改,它现在是http://docs.sqlalchemy.org/en/rel_0_9/orm/mapped_attributes.html#simple-validators – runejuhl