2010-02-23 99 views
6

是否有可能在SQLAlchemy中强制分配给映射列的最大字符串长度值?我想要的只是如果分配的字符串值比字符串类型的表格列的长度长,则会引发异常。SQLAlchemy - 最大列长度

谢谢

+0

请提供您所使用来定义表和映射到你的类的代码。 AFAIK,数据库应该引发一个通过SQLAlchemy传回的错误。请张贴代码提供一些关于您现在正在尝试的提示。 –

+0

@ S.Lott MySQL在插入/更新时不检查字符串长度。它静静地截断太长的字符串。 – codeape

回答

6

这是最简单的,只是通过属性重命名映射列,并代理其:

class Something(Base): 
    ... 
    _foo = Column('foo', String(123)) 

    @property 
    def foo(self): 
     return self._foo 

    @foo.setter 
    def foo(self, value): 
     if len(value) > _foo.type.length: 
      raise Exception("Value too long") 
     self._foo = value 

您可以轻松地分解出的创造,甚至使用类似formencode一个通用的验证框架。


如果你需要一个更SQLAlchemy的具体的解决方案,而且不介意使用特定的接口,然后SQLAlchemy的已经有属性的捕捉事件的扩展机制。使用验证器会是这个样子:

from sqlalchemy.orm.interfaces import AttributeExtension, InstrumentationManager 
from sqlalchemy.orm import ColumnProperty 

class InstallValidatorListeners(InstrumentationManager): 
    def post_configure_attribute(self, class_, key, inst): 
     """Add validators for any attributes that can be validated.""" 
     prop = inst.prop 
     # Only interested in simple columns, not relations 
     if isinstance(prop, ColumnProperty) and len(prop.columns) == 1: 
      col = prop.columns[0] 
      # if we have string column with a length, install a length validator 
      if isinstance(col.type, String) and col.type.length: 
       inst.impl.extensions.insert(0, LengthValidator(col.type.length)) 

class ValidationError(Exception): 
    pass 

class LengthValidator(AttributeExtension): 
    def __init__(self, max_length): 
     self.max_length = max_length 

    def set(self, state, value, oldvalue, initiator): 
     if len(value) > self.max_length: 
      raise ValidationError("Length %d exceeds allowed %d" % 
           (len(value), self.max_length)) 
     return value 

你会然后你想验证任何类设置__sa_instrumentation_manager__ = InstallValidatorListeners使用这个扩展。如果您希望它适用于从它派生的所有类,您也可以将其设置在基类上。

+0

是的,它解决了这个问题,但是我有几十个这样的列,所以使用这个属性不是很方便。使用SQLAlchemy类型系统的解决方案会更好。 – honzas

+0

我添加了一个可用于sqlalchemy特定验证程序的示例。 –

+0

是的,这种解决方案对我来说很理想,谢谢。 – honzas

0

这里有一个更新的版本,适合新的SQLAlchemy版本的事件系统:

class InstallValidatorListeners(InstrumentationManager): 
    def post_configure_attribute(self, class_, key, inst): 
     """Add validators for any attributes that can be validated.""" 
     prop = inst.prop 
     # Only interested in simple columns, not relations 
     if isinstance(prop, ColumnProperty) and len(prop.columns) == 1: 
      col = prop.columns[0] 
      if isinstance(col.type, String) and col.type.length: 
       sqlalchemy.event.listen(
        getattr(class_, key), 'set', LengthValidator(col.type.length), retval=True) 


class ValidationError(Exception): 
    pass 


class LengthValidator(AttributeExtension): 
    def __init__(self, max_length): 
     self.max_length = max_length 

    def __call__(self, state, value, oldvalue, initiator): 
     if len(value) > self.max_length: 
      raise ValidationError(
       "Length %d exceeds allowed %d" % (len(value), self.max_length)) 
     return value