-
Notifications
You must be signed in to change notification settings - Fork 252
Open
Description
功能请求:支持自定义数据类型的标准化API,包含Py2DB/DB2Py转换方法
当前问题
PonyORM现有的内置字段类型可能无法满足所有使用场景,特别是处理特殊数据类型(如压缩字符串或numpy数组)时。开发者需要一种标准化的方式来创建具有适当数据库序列化/反序列化的自定义字段类型。
提议方案
建议实现一个BaseType基类,允许开发者定义自定义字段类型,包含:
- 数据库行为规范(
__database_behavior__) - 验证方法(
validate) - Python到数据库的转换方法(
py2db) - 数据库到Python的转换方法(
db2py)
示例实现
import gzip
import numpy as np
import json
class BaseType:
"""PonyORM中自定义字段类型的基类"""
__database_behavior__ = None # 必须被重写为一个基本类型
@staticmethod
def validate(value):
"""验证值是否为正确类型"""
raise NotImplementedError
@staticmethod
def py2db(value):
"""将Python值转换为数据库表示形式"""
raise NotImplementedError
@staticmethod
def db2py(value):
"""将数据库表示形式转换回Python值"""
raise NotImplementedError
class GzipStringType(BaseType):
__database_behavior__ = bytes
@staticmethod
def validate(value: str):
if not isinstance(value, str):
raise ValueError("必须为字符串类型")
@staticmethod
def py2db(value: str) -> bytes:
if len(value) < 128: # 小字符串不压缩
return value.encode()
return gzip.compress(value.encode()) # 大字符串进行压缩
@staticmethod
def db2py(value: bytes) -> str:
try:
return gzip.decompress(value).decode() # 尝试解压
except gzip.BadGzipFile:
return value.decode() # 如果不是压缩数据,直接解码
class NDArrayType(BaseType):
__database_behavior__ = bytes
@staticmethod
def validate(value: np.ndarray):
if not isinstance(value, np.ndarray):
raise ValueError("必须为numpy.ndarray类型")
@staticmethod
def py2db(value: np.ndarray) -> bytes:
# 存储数组元数据和实际数据
metadata = json.dumps({
"shape": value.shape,
"dtype": str(value.dtype)
}).encode('utf-8')
data = value.tobytes()
return len(metadata).to_bytes(4, 'big') + metadata + data
@staticmethod
def db2py(value: bytes) -> np.ndarray:
# 从字节流重建numpy数组
meta_length = int.from_bytes(value[:4], 'big')
metadata = json.loads(value[4:4+meta_length].decode('utf-8'))
data = value[4+meta_length:]
return np.frombuffer(
data,
dtype=np.dtype(metadata["dtype"])
).reshape(metadata["shape"])优势
- 可扩展性:开发者可以为特殊需求创建自定义类型
- 类型安全:内置验证确保数据完整性
- 高效性:针对特定数据类型的优化存储(如对大字符串的压缩)
- 一致性:自定义字段类型的标准化接口
建议的集成方式
可以这样集成到PonyORM的实体定义中:
from pony.orm import *
db = Database()
class MyEntity(db.Entity):
compressed_data = Required(GzipStringType) # 必填的压缩字符串字段
array_data = Optional(NDArrayType) # 可选的numpy数组字段其他考虑
- 向后兼容:应确保不影响现有代码
- 性能影响:转换方法应尽可能高效
- 错误处理:需要完善的错误处理机制
- 文档支持:需要详细的文档说明如何使用自定义类型
这个提案是否与PonyORM的设计理念相符?期待听到您的想法和建议。
Metadata
Metadata
Assignees
Labels
No labels