属性(Properties)#
模块:restalchemy.dm.properties
属性是 DM 模型定义字段与管理值的核心机制。
基础类#
AbstractProperty#
所有属性的抽象基类:
value:当前值。set_value_force(value):强制设置值,绕过只读/ID 限制。is_dirty():判断值是否自初始化以来发生变化。is_prefetch():是否用于预取(prefetch)。
Property#
通用属性实现,用于标量和结构化字段。
构造函数:
Property(
property_type,
default=None,
required=False,
read_only=False,
value=None,
mutable=False,
example=None,
)
关键点:
property_type必须是types.BaseType实例。default可以是值或可调用对象;可调用对象会在初始化时执行一次。- 若传入
value,则优先于default。 mutable=False时,初始值会被拷贝,以便正确实现is_dirty()。- 无效值会触发
restalchemy.common.exceptions中的异常。
IDProperty#
用于 ID 字段的专用属性:
is_id_property()返回True。- 与
ModelWithID、ModelWithUUID搭配使用。
PropertyCreator 与工厂函数#
PropertyCreator#
保存创建具体属性实例所需的信息:
- 属性类(
Property或IDProperty)。 - DM 类型实例(如
types.String()、types.Integer())。 - 构造函数参数。
prefetch标志。
在模型类定义中,真正赋值给类属性的是 PropertyCreator。
property()#
模型中最常用的工厂函数:
from restalchemy.dm import properties, types
class Foo(models.Model):
value = properties.property(types.Integer(), required=True)
参数:
property_type:types.BaseType实例。id_property:若为True,使用IDProperty。property_class:自定义属性类,必须继承AbstractProperty。- 其它关键字参数传递给属性构造函数(
default、required、read_only、mutable、example等)。
便捷工厂函数#
required_property(property_type, *args, **kwargs):自动设置required=True。readonly_property(property_type, *args, **kwargs):自动设置read_only=True且required=True。
示例:
class User(models.ModelWithUUID):
email = properties.required_property(types.Email())
created_at = properties.readonly_property(types.UTCDateTimeZ(), default=datetime.datetime.now)
PropertyCollection 与 PropertyManager#
PropertyCollection#
在类级别上保存字段定义:
- 映射 字段名 →
PropertyCreator或嵌套PropertyCollection。 - 实现映射协议。
sort_properties()按名称排序(主要用于测试)。instantiate_property(name, value=None)创建具体属性实例。
PropertyManager#
在实例级别管理属性:
- 根据
PropertyCollection与初始值构建实际属性对象。 properties:只读映射 字段名 → 属性实例。value:字段名到“原始值”的字典(可读写)。
Model.pour() 使用 PropertyManager 构建实例状态:
如果缺少必填属性,PropertyManager 会抛出带有字段名的 PropertyRequired。
容器与嵌套结构#
container()#
创建嵌套属性集合,用于一组相关字段:
address_container = properties.container(
city=properties.property(types.String()),
zip_code=properties.property(types.String()),
)
class User(models.ModelWithUUID):
name = properties.property(types.String(), required=True)
address = address_container
运行时 address 是一个嵌套的 PropertyManager:
修改跟踪(Dirty Tracking)#
Property 与 Relationship 都支持 is_dirty():
Property比较当前值与初始值。Relationship比较当前关联对象与初始值。
Model.is_dirty() 遍历所有字段,只要有一个字段“脏”,就返回 True。
使用建议#
- 在属性中尽量使用 DM 类型(
types.String、types.Integer等),而不是原生 Python 类型。 - 使用
id_property=True或ModelWithUUID/ModelWithID明确标记主键字段。 - 根据需要使用
required_property()、readonly_property()提升可读性。 - 使用
container()表达逻辑分组或嵌套 JSON 结构。