gpt4 book ai didi

python - 在声明中指定时如何自动验证字符串/Unicode 列最大长度?

转载 作者:行者123 更新时间:2023-12-02 02:54:48 25 4
gpt4 key购买 nike

SQLAlchemy 允许在声明 String 列时指定长度:

foo = Column(String(10))

如 SQL 中所示:

foo VARCHAR(10)

我知道某些 DBMS 在表中创建行时使用此长度值来分配内存。但有些 DBMS(如 SQLite)不关心它,仅为了与 SQL 标准兼容而接受此语法。但某些 DBMS(如 MySQL)要求指定它。

就我个人而言,我喜欢指定某些文本数据的最大长度,因为它有助于设计 UI,因为您知道显示它所需的区域。

此外,我认为这将使我的应用程序行为在不同的 DBMS 中更加一致。

因此,我想通过根据声明的长度检查其长度(当声明长度时)来验证插入时 String/Unicode 列的值。

检查约束

第一个解决方案是使用 check constraint :

from sqlalchemy import CheckConstraint, Column, Integer, String, create_engine
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine("sqlite:///:memory:", echo=True)
Base = declarative_base(bind=engine)
Session = sessionmaker(bind=engine)


class Foo(Base):
__tablename__ = "Foo"

id = Column(Integer, primary_key=True)
bar = Column(String(10), CheckConstraint("LENGTH(bar) < 10"))


Base.metadata.create_all()

if __name__ == "__main__":
session = Session()
session.add(Foo(bar="a" * 20))

try:
session.commit()
except IntegrityError as e:
print(f"Failed with: {e.orig}")

它可以工作,但 SQL 约束表达式不是由 SQLAlchemy 生成的。因此,如果 DBMS 需要不同的语法,则可能需要一些自定义生成。

验证器

我还尝试使用 SQLAlchemy validator :

class Foo(Base):
__tablename__ = "Foo"

id = Column(Integer, primary_key=True)
bar = Column(String(10))

@validates("bar")
def check_bar_length(self, key, value):
column_type = getattr(type(self), key).expression.type
max_length = column_type.length

if len(value) > max_length:
raise ValueError(
f"Value '{value}' for column '{key}' "
f"exceed maximum length of '{max_length}'"
)

return value
try:
Foo(bar="a" * 20)
except ValueError as e:
print(f"Failed with: {e}")

现在,最大长度是从声明的长度推断出来的。

检查是在实体创建时完成的,而不是在提交时完成的。不知道会不会有问题。

自定义类型

上面显示的两种解决方案都需要对每列应用验证。我正在寻找一种解决方案来自动检查具有声明长度的 String/Unicode 列。

使用 custom type可能是解决方案。但它看起来像是一个丑陋的黑客,因为自定义类型不是为了数据验证而是为了数据转换。

那么,您是否考虑另一种解决方案,也许是我不知道的 SQLAlchemy 功能,这将帮助我将检查自动添加到所有 String 列,其中 length 已指定?

最佳答案

另一个选项可能是显式定义表并分解字符串列定义,以便为每个字符串列创建检查约束,而无需重复它。

def string_column(name, length):
check_str = "LENGTH({}) < {}".format(name, length)
return Column(name, String(length), CheckConstraint(check_str))


class Foo(Base):
__table__ = Table("Foo", Base.metadata,
Column("id", Integer, primary_key=True),
string_column("bar", 10),
string_column("name", 15))

关于python - 在声明中指定时如何自动验证字符串/Unicode 列最大长度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57809914/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com