DM + SQL storage how-to#
本指南展示如何使用 RESTAlchemy 将 DM 模型持久化到 SQL 数据库。
你将学会:
- 使用
ModelWithUUID与SQLStorableMixin定义可持久化的 DM 模型。 - 配置 SQL 引擎(MySQL 或 PostgreSQL)。
- 通过
.save()、.delete()与Model.objects执行 CRUD 操作。 - 使用过滤器构造查询条件。
示例基于 examples/dm_mysql_storage.py 与 examples/dm_pg_storage.py。
前置条件#
- 已安装 RESTAlchemy(见
installation.md)。 - 有一套正在运行的数据库:
- MySQL/MariaDB,或
- PostgreSQL。
- 安装了对应的 Python 驱动,例如:
mysql-connector-python(MySQL)。psycopg[binary](PostgreSQL)。- 数据库中已存在与模型对应的表结构(可通过迁移工具创建)。
1. 为 SQL 定义 DM 模型#
基本模式:
- 继承自
models.ModelWithUUID(或其它ModelWithID)。 - 同时继承
orm.SQLStorableMixin。 - 设置
__tablename__。 - 使用 DM 属性与类型定义字段。
示例(简化自 dm_mysql_storage.py):
from restalchemy.dm import models, properties, relationships, types
from restalchemy.storage.sql import orm
class FooModel(models.ModelWithUUID, orm.SQLStorableMixin):
__tablename__ = "foos"
foo_field1 = properties.property(types.Integer(), required=True)
foo_field2 = properties.property(types.String(), default="foo_str")
class BarModel(models.ModelWithUUID, orm.SQLStorableMixin):
__tablename__ = "bars"
bar_field1 = properties.property(types.String(min_length=1, max_length=10))
foo = relationships.relationship(FooModel)
2. 配置 SQL 引擎#
通过 restalchemy.storage.sql.engines.engine_factory 创建引擎实例。
MySQL 示例#
from restalchemy.storage.sql import engines
engines.engine_factory.configure_factory(
db_url="mysql://user:password@127.0.0.1:3306/test",
)
PostgreSQL 示例#
from restalchemy.storage.sql import engines
engines.engine_factory.configure_factory(
db_url="postgresql://postgres:password@127.0.0.1:5432/ra_tests",
)
通常在应用启动时调用一次 configure_factory()。之后所有带有 SQLStorableMixin 的模型会通过 engine_factory.get_engine() 获得引擎。
可选参数:
config:引擎配置(连接池大小、超时等)。query_cache:是否启用会话级查询缓存。
3. 创建表与迁移#
RESTAlchemy 不会自动创建数据表,而是依赖显式迁移。
迁移命令在 README.rst 中有说明:
ra-new-migration:创建新的迁移文件。ra-apply-migration:应用迁移。
示例文件中包含以注释形式给出的 SQL 结构,例如 dm_mysql_storage.py:
CREATE TABLE `foos` (
`uuid` CHAR(36) NOT NULL,
`foo_field1` INT NOT NULL,
`foo_field2` VARCHAR(255) NOT NULL,
PRIMARY KEY (`uuid`)
) ENGINE = InnoDB;
CREATE TABLE `bars` (
`uuid` CHAR(36) NOT NULL,
`bar_field1` VARCHAR(10) NOT NULL,
`foo` CHAR(36) NOT NULL,
CONSTRAINT `_idx_foo` FOREIGN KEY (`foo`) REFERENCES `foos`(`uuid`)
) ENGINE = InnoDB;
你可以按自己的环境调整这些结构,或生成产生同类 DDL 的迁移。
4. 基本 CRUD 操作#
在配置好引擎并创建表之后,可以像操作普通 DM 模型一样进行 CRUD:
创建与保存#
读取数据#
# 所有 Bar
all_bars = list(BarModel.objects.get_all())
# 根据主键读取一个 Bar
same_bar = BarModel.objects.get_one(filters={"uuid": bar1.get_id()})
# 获取某个 Foo 下的所有 Bar
bars_for_foo = list(BarModel.objects.get_all(filters={"foo": foo1}))
print(bar1.as_plain_dict())
更新#
foo2 = FooModel(foo_field1=11, foo_field2="some text")
foo2.save()
foo2.foo_field2 = "updated text"
foo2.save()
删除#
5. 过滤(Filters)#
过滤器定义在 restalchemy.dm.filters 中,可传递给 get_all() 与 get_one()。
简单过滤条件#
from restalchemy.dm import filters
one = FooModel.objects.get_one(filters={"foo_field1": filters.EQ(10)})
greater = list(
FooModel.objects.get_all(filters={"foo_field1": filters.GT(5)})
)
subset = list(
FooModel.objects.get_all(filters={"foo_field1": filters.In([5, 6])})
)
not_subset = list(
FooModel.objects.get_all(filters={"foo_field1": filters.NotIn([1, 2])})
)
复杂表达式#
可以用 AND 与 OR 表达式构建复杂条件:
filter_expr = filters.OR(
filters.AND({
"foo_field1": filters.EQ(1),
"foo_field2": filters.EQ("2"),
}),
filters.AND({"foo_field2": filters.EQ("3")}),
)
foo = FooModel.objects.get_one(filters=filter_expr)
6. 事务与显式会话#
默认情况下,每次操作使用独立的会话与事务。
若需要将多次操作合并到一个事务中,可以使用 engine.session_manager()。
使用 engine.session_manager()#
from restalchemy.storage.sql import engines
engine = engines.engine_factory.get_engine()
with engine.session_manager() as session:
foo = FooModel(foo_field1=42)
foo.save(session=session)
bar = BarModel(bar_field1="x", foo=foo)
bar.save(session=session)
# 如果这里发生异常,两条 INSERT 都会被回滚。
with 代码块中的所有操作共享同一个会话与事务。
你也可以把从引擎获取的会话对象复用到代码的其他位置:把 session= 传给 .save()、.delete() 或集合方法即可。
小结#
- 通过
ModelWithUUID+SQLStorableMixin定义持久化模型,并设置__tablename__。 - 使用
engine_factory.configure_factory()配置 SQL 引擎。 - 使用迁移工具创建/更新数据库表。
- 使用
.save()、.delete()、Model.objects.get_all()/get_one()实现 CRUD。 - 使用 DM 过滤器表示查询条件。
- 在需要时通过显式会话控制事务边界。