SQLAlchemy——我可以在 DDL 中将空字符串映射到 null 吗?我想要一个可为 null 的整数列在插入或更新时将 '' 转换为 NULL

SQLAlchemy--can I map an empty string to null in the DDL? I want a nullable integer column to translate '' to NULL on insert or update

我有一个 SQLAlchemy 模型,其中一个整数列是从 HTML 表单填充的(我正在使用 Flask 和 WTForms-alchemy,我试图避免在路由中编写自定义代码)。如果用户没有在表单上为这个整数输入值,从表单填充对象的代码最终会尝试为该列放入一个空字符串,并且 MySQL 会抱怨这不是一个整数值。帮助人们搜索:我从 Incorrect integer value: '' for column ....

开始的错误

我不想使用 sql_mode='' hack,人们建议这样做是为了让 MySQL 回到每当你给它不正确的数据时进行猜测的旧行为,因为我无法控制最终将用于的 MySQL 服务器。

我想要的是类似于默认列规范的东西,只是我不想在没有传入任何内容时指定默认值,而是想拦截尝试放入空字符串并将其替换为 None 我认为它在进入数据库时​​会被转换为 null。

有没有办法在模型定义中做到这一点?我意识到这可能会导致性能下降,但吞吐量在此应用程序中并不是什么大问题。

我找到了一个方法。 validates 装饰器可以在进入的过程中改变一个值。我是这样做的:

from sqlalchemy.orm import validates

class Task(Base):
    __tablename__ = 'task'

    id = Column(INTEGER(11), primary_key=True)

    time_per_unit = Column(INTEGER(11))


    @validates('time_per_unit')
    def empty_string_to_null(self, key, value):
        if isinstance(value,str) and value == '':
            return None
        else:
            return value

我 运行 遇到了类似的问题并创建了一个装饰器,然后可以在该字段的 setter 上使用它。这允许轻松重用,但确实需要为该字段使用混合 属性 和 setter。

helpers.py

def noneIfEmptyString(func):
@functools.wraps(func)
def wrapped_function(*args, **kwargs):
    """Decorator to convert empty string to None """
    for arg in args:
        if arg == '':
            arg = None
    for k,v in kwargs.items():
        if v == '':
            kwargs[k] = None
    return func(*args, **kwargs)
return wrapped_function

Models.py

_columnName = db.Column(db.String(120))

@hybrid_property
def columnName(self):
    return self._columnName

@columnName.setter
@noneIfEmptyString
def columnName(self, name):
    self._columnName = name;