6

How can I automatically truncate string values in a data model across many attributes, without explicitly defining a @validates method for each one?

My current code:

from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import validates

class MyModel:
    __tablename__ = 'my_model'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String(40), nullable=False, unique=True)

    # I can "force" truncation to my model using "validates"
    # I'd prefer not to use this solution though...
    @validates('name')
    def validate_code(self, key, value):
        max_len = getattr(self.__class__, key).prop.columns[0].type.length
        if value and len(value) > max_len:
            value = value[:max_len]
        return value

My concern is that my ORM will span many tables and fields and there's a high risk of oversight in including attributes in string length validation. In simpler words, I need a solution that'll scale. Ideally, something in my session configuration which'll automatically truncate strings that are too long...

1 Answer 1

10

You could create a customised String type that automatically truncates its value on insert.

import sqlalchemy.types as types


class LimitedLengthString(types.TypeDecorator):
    impl = types.String

    def process_bind_param(self, value, dialect):
        return value[:self.impl.length]

    def copy(self, **kwargs):
        return LimitedLengthString(self.impl.length)


class MyModel:
    __tablename__ = 'my_model'

    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(LimitedLengthString(40), nullable=False, unique=True)

The extended type will still create VARCHAR(40) in the database, so it should be possible to replace String(40) with LimitedLengthString(40)* in your code without a database migration.


* You might want to choose a shorter name.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.