Files
GVSDSDK/model_utils.py
T
TermiNexus 9be878b84a feat(sdk): 通用查询与工具层下沉,新增 App 体系镜像模型
P1 通用查询:auth/managers.py 新增 20 个查询方法(Role/Company/Department/Position/Menu/Tenant 六个 Manager);auth/ram.py 新增 RAMManager.ListPolicyResourceUUIDs;stats/manager.py 新增 StatsManager.ListAutoResetConfigs。

P2 App 体系:models.py 新增 App/TenantApp/CompanyApp/UserApp/AppConfig 五个 managed=False 镜像模型,字段与业务侧逐一对齐。

P3 工具下沉:新增 config.py 配置注入层与 money/json_encoder/celery_utils/exception_handler/redis_lock/ip_filter/storage/datetime_utils/string_utils 九个工具模块;model_utils.UUIDObj 增加 PascalCase 别名 Str/Bytes/UUID 与模块级转换函数。

同时移除 commission/stats/CashBook 镜像模型的重复索引声明,消除 Django models.E030。
2026-09-13 21:57:45 +08:00

140 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import re
import uuid
from functools import lru_cache
class UUIDObj:
__slots__ = ('_raw',)
def __init__(self, val):
if val is None:
self._raw = None
elif isinstance(val, UUIDObj):
self._raw = val._raw
elif isinstance(val, uuid.UUID):
self._raw = val
elif isinstance(val, bytes):
if len(val) != 16:
raise ValueError(
'UUIDObj expects 16-byte bytes, got %d bytes' % len(val)
)
self._raw = uuid.UUID(bytes=val)
elif isinstance(val, str):
self._raw = uuid.UUID(val)
else:
self._raw = uuid.UUID(str(val))
@property
def str(self):
if self._raw is None:
return None
return str(self._raw)
@property
def bytes(self):
if self._raw is None:
return None
return self._raw.bytes
@property
def uuid(self):
return self._raw
# ── PascalCase 别名(兼容旧 gvsds.common.UUID 的 Str/Bytes/UUID 属性) ──
@property
def Str(self):
return self.str
@property
def Bytes(self):
return self.bytes
@property
def UUID(self):
return self._raw
def __str__(self):
return self.str or ''
def __repr__(self):
return f'UUIDObj({self.str})'
def __eq__(self, other):
if isinstance(other, UUIDObj):
return self._raw == other._raw
if isinstance(other, uuid.UUID):
return self._raw == other
if isinstance(other, str):
return self.str == other
if isinstance(other, bytes) and len(other) == 16:
return self.bytes == other
return NotImplemented
def __hash__(self):
return hash(self._raw)
def __bool__(self):
return self._raw is not None
def __len__(self):
# UUID 固定 16 字节;空值返回 0
return 16 if self._raw is not None else 0
@lru_cache(maxsize=1)
def _GetUserModel():
"""动态获取 User 模型——保持 SDK 独立性,不硬依赖 gvsds 内部模块。
回退顺序:
1. gvsdsdk.User(抽象基类,会触发 LookupError)
2. 业务子项目中的具体 User 子类(users.User / core.User)
使用 lru_cache 缓存避免热路径重复调用 apps.get_model()。
测试中如需重置缓存,调用 _GetUserModel.cache_clear()。
"""
from django.apps import apps
for app_label in ('gvsdsdk', 'users', 'core'):
try:
return apps.get_model(app_label, 'User')
except LookupError:
continue
raise LookupError("未找到 User 模型,请在业务子项目中定义 User 子类")
# ── UUID 便捷函数(兼容旧 gvsds.common.UUID 的模块级 API) ──
def NewUUID():
"""生成随机 UUIDObj"""
return UUIDObj(uuid.uuid4())
def NewUUIDBytes():
"""生成随机 UUID 的 16 字节形式"""
return uuid.uuid4().bytes
def NewUUIDStr():
"""生成随机 UUID 字符串"""
return str(uuid.uuid4())
def UUIDToBytes(value):
"""任意 UUID 表示 → 16 字节"""
return UUIDObj(value).bytes
def UUIDToStr(value):
"""任意 UUID 表示 → 字符串"""
return UUIDObj(value).str
def BytesToUUIDStr(value):
"""16 字节 → UUID 字符串"""
return str(uuid.UUID(bytes=value))
def StrToUUIDBytes(value):
"""UUID 字符串 → 16 字节"""
return uuid.UUID(value).bytes