我基于SQLAlchemy example创建了一个TypeDecorator,它在32个字符的十六进制字符串和存储UUID的BINARY
数据库列之间进行转换:
from __future__ import absolute_import
import uuid
from sqlalchemy import types, func
#https://docs.sqlalchemy.org/en/13/core/custom_types.html#backend-agnostic-guid-type
class HashColumn(types.TypeDecorator):
impl=types.BINARY
def process_bind_param(self, value, dialect):
if value is not None:
return uuid.UUID(hex=value).bytes
def process_result_value(self, value, dialect):
return uuid.UUID(bytes=value).hex
def copy(self, **kw):
return HashColumn(self.impl.length)
型号:
def get_uuid():
return uuid.uuid4().hex
class School(db.Model):
"""
description: A School
"""
__tablename__ = "schools"
id = db.Column('school_id', HashColumn(length=16), primary_key=True, default=get_uuid)
...
但是,我遇到的问题是,从SQLAlchemy模型生成的棉花糖模式没有将此列视为32个字符的字符串:
Schema:
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
...
class SchoolSchema(SQLAlchemyAutoSchema):
class Meta:
model = School
include_relationships = True
load_instance = True
include_fk = True
...
以我的代码:
try:
new_object = SchoolSchema().load(data, session=db.session)
except ValidationError as err:
print(err.messages)
print(err.valid_data)
以完全有效的UUID为a5fad20c691546ae8871390d980aae6d
运行此代码时,棉花糖将引发验证错误并提供以下输出:
{"id": ["Longer than maximum length 16."]}
由于我想在使用过程中将UUID的格式设置为32个字符的十六进制字符串(或python UUID,如果适用),并在存储到数据库中之前将其转换为BINARY(16)
,因此我需要摆脱此验证错误,但是我不确定该怎么做,因为更改SQLAlchemy模型上的length参数将意味着将数据库表创建为BINARY(32)
而不是BINARY(16)
,从而将长度加倍。
是否可以设置SQLAlchemy TypeDecorator
,以便它在数据库中存储一种长度(BINARY(16)
)的类型,但与Python和/或SQLAlchemy呈现不同的长度(CHAR(32)
),从而棉花糖可以正确验证长度为32个字符的字符串吗?
我已经在StackOverflow上寻找了类似这样的其他问题:
但是这似乎与转换类型本身有关,这已经在示例代码中完成了。我似乎找不到任何提及如何转换类型的[[length。
CHAR
列而不是二进制列,并使用load_dialect_impl
更改呈现给数据库的类型,并指定不同的长度作为参数class HashColumn(types.TypeDecorator):
impl=types.CHAR
def load_dialect_impl(self, dialect):
return dialect.type_descriptor(types.BINARY(16))
...
(该课程的其余部分基本上与问题中的相同)此更改使我可以将数据库模型中的
HashColumn(length=16)
定义更改为HashColumn(length=32)
,从而使棉花糖可以正确解释长度。