我創建了一個基于SQLAlchemy 示例的 TypeDecorator ,它在 32 個字符的十六進制字符串和BINARY存儲 UUID 的數據庫列之間進行轉換:from __future__ import absolute_importimport uuidfrom sqlalchemy import types, func#https://docs.sqlalchemy.org/en/13/core/custom_types.html#backend-agnostic-guid-typeclass 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().hexclass School(db.Model): """ description: A School """ __tablename__ = "schools" id = db.Column('school_id', HashColumn(length=16), primary_key=True, default=get_uuid) ...但是,我遇到的問題是我的棉花糖模式(從 SQLAlchemy 模型生成)沒有將此列視為 32 個字符的字符串:架構: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,marshmallow 會拋出驗證錯誤并提供以下輸出:{"id": ["Longer than maximum length 16."]}由于我想在使用過程中將 UUID 格式化為 32 個字符的十六進制字符串(或適用的 python UUID),并BINARY(16)在存儲到數據庫之前轉換為正確的格式,因此我需要消除此驗證錯誤,但我不確定如何做到這一點,因為更改 SQLAlchemy 模型上的長度參數將意味著將創建數據庫表BINARY(32)而不是BINARY(16),將長度加倍。是否可以設置 SQLAlchemyTypeDecorator以便它在數據庫中存儲一種長度 ( BINARY(16)) 的類型,但向CHAR(32)Python 和/或 SQLAlchemy 提供不同的長度 ( ) 以便 marshmallow 可以正確地將長度驗證為 32 個字符的字符串?
1 回答

holdtom
TA貢獻1805條經驗 獲得超10個贊
到目前為止,我找到了兩種方法來解決這個問題:
調整 TypeDecorator 的類型,使其像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)定義從我的 DB 模型更改為HashColumn(length=32),從而允許 marshmallow 正確解釋長度。
或者,我可以更改我的 API PATCH/更新端點的實現以從數據庫中獲取和更新現有對象,而不是創建一個全新的對象并嘗試合并它們的值。這完全刪除了 Marshmallow 驗證,因為 ID 不再用于創建新對象,但是,對我來說,這感覺像是一種太多的解決方法,并且意味著,因為沒有使用 Marshmallow 驗證,它也不會驗證任何其他數據字段。
添加回答
舉報
0/150
提交
取消