2010-02-23 27 views
6

jest to możliwe w SQLAlchemy do wymuszenia maksymalnej długości łańcucha wartości przypisanej do zamapowanej kolumny? Wszystko, co chcę, to podnieść wyjątek, jeśli przypisana wartość ciągu jest dłuższa niż długość odpowiedniej kolumny tabeli typu STRING.SQLAlchemy - maksymalna długość kolumny

Dziękuję

+0

Proszę podać kod, którego używasz do zdefiniowania tabeli i mapowanie do swojej klasy. AFAIK, baza danych powinna wywołać błąd, który propaguje ponownie poprzez SQLAlchemy. Wpisz kod, by podać wskazówkę dotyczącą tego, co próbujesz teraz. –

+0

@ S.Lott MySQL nie sprawdza długości łańcucha przy wstawianiu/aktualizacji. Cicho obcinuje ciągi, które są zbyt długie. – codeape

Odpowiedz

6

Najłatwiej po prostu zmienić nazwę odwzorowaną kolumnę i pełnomocnika go przez nieruchomości:

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 

Można łatwo czynnikiem się tworzenie własności, a nawet wykorzystać ogólny ramy poprawności takiego formencode .


Jeśli potrzebujesz więcej sqlalchemy konkretne rozwiązanie i nie przeszkadza przy użyciu specyficznych interfejsów, a następnie SQLAlchemy ma mechanizm wewnętrzny do przechwytywania zdarzeń na atrybutach. Walidator użyciem że będzie wyglądać mniej więcej tak:

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 

byłoby wtedy użyć tego rozszerzenia poprzez ustawienie __sa_instrumentation_manager__ = InstallValidatorListeners na dowolnej klasy ma zostać zatwierdzone. Możesz także ustawić go w klasie Base, jeśli chcesz zastosować do wszystkich klas pochodnych od niego.

+0

Tak, rozwiązuje problem, ale mam kilkadziesiąt takich kolumn, więc korzystanie z właściwości nie jest bardzo wygodne. Rozwiązanie korzystające z systemu typu SQLAlchemy byłoby lepsze. – honzas

+0

Dodałem przykład, który może być użyty dla walidatorów specyficznych dla sqlalchemy. –

+0

Tak, tego rodzaju rozwiązanie jest idealne dla mnie, dziękuję. – honzas

0

Tutaj jest zaktualizowana wersja, która pasuje do systemu zdarzeń nowszych wersjach 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