2010-02-23 5 views
6

Возможно ли в SQLAlchemy обеспечить максимальную длину строки значения, присвоенного сопоставленному столбцу? Все, что я хочу, это создать исключение, если назначенное строковое значение больше длины соответствующего столбца таблицы типа STRING.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 на любой класс, который вы хотите проверены. Вы также можете просто установить его в классе Base, если хотите, чтобы он применим ко всем классам, полученным из него.

+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 
Смежные вопросы