自动截断sqlalchemy的ORM(postgresql数据库)中的字符串

Yaa*_*ler 3 python postgresql sqlalchemy

如何自动截断数据模型中多个属性的字符串值,而不需要@validates为每个属性显式定义一种方法?

我当前的代码:

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
Run Code Online (Sandbox Code Playgroud)

我担心的是,我的 ORM 将跨越许多表和字段,并且在字符串长度验证中包含属性时存在很高的监督风险。简而言之,我需要一个可扩展的解决方案。理想情况下,我的会话配置中的某些内容会自动截断太长的字符串......

sna*_*erb 6

您可以创建一个自定义的 String 类型,该类型会在插入时自动截断其值。

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)
Run Code Online (Sandbox Code Playgroud)

扩展类型仍将VARCHAR(40)在数据库中创建,因此应该可以在代码中用 *String(40)替换,而无需数据库迁移。LimitedLengthString(40)


* 您可能想选择一个较短的名称。