Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLAlchemy - maximum column length

is it possible in SQLAlchemy to enforce maximum string length of value assigned to mapped column? All I want is to raise an exception if an assigned string value is longer then the length of the corresponding table column of type STRING.

Thank you

like image 294
honzas Avatar asked Feb 23 '10 09:02

honzas


People also ask

What is PickleType?

PickleType. Holds Python objects, which are serialized using pickle.

What is nullable SQLAlchemy?

From SQLAlchemy docs: nullable – If set to the default of True, indicates the column will be rendered as allowing NULL, else it's rendered as NOT NULL. This parameter is only used when issuing CREATE TABLE statements.

What is enum in SQLAlchemy?

Enum is a class within the sqlalchemy. types module of the SQLAlchemy project.


1 Answers

It's easiest to just rename the mapped column and proxy it through a property:

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 

You can easily factor out the property creation, and even use a generic validation framework like formencode.


If you need a more SQLAlchemy specific solution and don't mind using specific interfaces, then SQLAlchemy has an extension mechanism for capturing events on attributes. A validator using that would look something like this:

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

You would then use this extension by setting __sa_instrumentation_manager__ = InstallValidatorListeners on any class you want validated. You can also just set it on the Base class if you want it to apply to all classes derived from it.

like image 111
Ants Aasma Avatar answered Sep 21 '22 00:09

Ants Aasma