是否可以在SQLAlchemy中强制分配给映射列的最大字符串长度值?如果指定的字符串值比STRING类型的相应表列的长度长,那么我想要的是引发异常。
谢谢
答案 0 :(得分: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
来使用此扩展程序。如果希望它应用于从它派生的所有类,也可以在Base类上设置它。
答案 1 :(得分: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