pyre-sqlalchemy-db
基于 SQLAlchemy 2.0 的轻量 ORM 增强库:声明式字段、事务管理、分页、软删除、雪花 ID 以及完整的异步支持,并与 Flask / Starlette 等框架无侵入集成。
✨ 特点
- 🧱 声明式字段 —
StringField、DateTimeField、ForeignKeyField开箱即用,参数透传mapped_column。 - 🔁 事务管理 —
transactional/local_transaction,支持REQUIRED/NEW/MANDATORY传播与隔离级别。 - ⚡ 异步支持 —
async_transactional/Model.async_query,同一套模型同步、异步通用。 - 🧩 常用 Mixin — 主键、创建/更新时间、软删除、操作人,按需组合。
- 🆔 主键策略 — 自增、雪花 ID、UUID 三种,一行切换。
- 🔌 多数据源 — 按 schema 绑定多个引擎,模型自动路由。
- 📤 序列化 —
to_dict()内置循环引用保护与日期 / Decimal / 枚举编码。 - 🪶 框架无关 — 核心不依赖任何 Web 框架,可选接入 Flask 应用上下文。
📦 安装
pip install pyre-sqlalchemy-db
按需安装可选依赖:
pip install "pyre-sqlalchemy-db[async]" # greenlet / aiosqlite / aiomysql / asyncpg
pip install "pyre-sqlalchemy-db[mysql]"
pip install "pyre-sqlalchemy-db[flask]"
💡 一个简单的例子
from sqlalchemy_db import SQLAlchemyDB, models
db = SQLAlchemyDB("sqlite:///demo.db")
class User(models.PkMixin, models.TimestampMixin, models.Model):
__tablename__ = "user"
name = models.StringField(50, comment="用户名")
age = models.IntegerField(default=0)
字段、模型与 Mixin 统一从 models 命名空间取用(models 即 sqlalchemy_db.models 子包)。
👩💻 目录结构
sqlalchemy-db
├── sqlalchemy_db
│ ├── __init__.py # 对外导出
│ ├── app.py # 框架集成入口
│ ├── transaction.py # 同步事务
│ ├── async_transaction.py # 异步事务
│ ├── snowflake.py # 雪花 ID 生成
│ ├── encoders.py # 序列化编码器
│ ├── exceptions.py # 异常体系
│ ├── models/ # Model / 字段 / Mixin / 查询
│ ├── globals.py # 实例解析
│ ├── constants.py
│ └── utils.py
├── examples/ # 可运行示例
├── tests/ # 单元测试
└── setup.py
🚀 快速开始
from sqlalchemy_db import SQLAlchemyDB, Page, local_transaction
db = SQLAlchemyDB("sqlite:///demo.db")
db.create_all()
# 写入
with local_transaction():
user = User(name="Alice", age=18)
user.insert()
print(user.id) # 1
# 更新与删除
with local_transaction():
user.save()
user.delete()
# 查询与分页
with local_transaction():
User.query.get_by_id_or_404(1)
User.query.select(User.age >= 18, order_by=User.id.desc())
page = Page(page=1, page_size=20)
User.query.select_page(page)
page.get_data() # 数据列表
page.get_count() # 总条数
Model.query在访问时即从当前会话上下文取 Session,因此所有查询都要运行在local_transaction()/transactional上下文内。否则库会告警事务上下文不会自动回收。
🧱 模型
字段
| 字段 | 对应类型 |
|---|---|
StringField(255) |
String |
TextField() / MediumtextField() |
Text / MEDIUMTEXT |
IntegerField / BigIntegerField / SmallIntegerField |
整型 |
FloatField / NumericField / DecimalField |
浮点 / 精确数值 |
BooleanField() |
Boolean |
DateField / DateTimeField / TimeField |
日期时间 |
JSONField() |
JSON |
BinaryField() |
LargeBinary |
EnumField / IntEnumField / StrEnumField |
枚举 |
ForeignKeyField("user.id") |
外键 |
AutoPkField(pk_type=...) |
主键(AUTO / SNOWFLAKE / UUID) |
所有字段均透传 mapped_column 参数,nullable、comment、server_default、index、
unique、sort_order 照常可用。
Mixin
| Mixin | 说明 |
|---|---|
PkMixin |
提供 id 主键 |
TimestampMixin |
自动维护 create_time / update_time |
SoftDeleteMixin |
提供 delete_time 列与软删除查询支持 |
Model |
基础模型,内置实例级 insert / save / delete |
主键策略
from sqlalchemy_db import PkType, models
class Order(models.Model):
__tablename__ = "order"
id = models.AutoPkField(pk_type=PkType.SNOWFLAKE)
序列化
user.to_dict()
user.to_dict(exclude={"age"}, exclude_none=True)
User.from_dict({"name": "Bob", "age": 20})
User.from_entity(pydantic_model)
🔍 查询
Model.query / Model.async_query 提供统一的链式查询入口。查询须在会话上下文内执行:
with local_transaction():
User.query.get_by_id(1) # 按主键
User.query.get_by_id_or_404(1) # 不存在抛 NotFoundDataException
User.query.get_one(User.name == "Alice")
User.query.select(User.age >= 18, order_by=User.id.desc())
User.query.select_batch_ids([1, 2, 3])
User.query.select_count(User.is_active.is_(True))
User.query.delete_by_id_or_404(1)
软删除:
with local_transaction():
User.query.with_not_trashed().all() # 排除已删除
User.query.only_trashed().all() # 仅已删除
User.query.with_trashed().all() # 全部
🔁 事务
from sqlalchemy_db import transactional, local_transaction, Propagation, Isolation
@transactional
def create_user(name: str):
User(name=name).insert()
with local_transaction():
User(name="Bob").insert()
@transactional(propagation=Propagation.NEW, isolation=Isolation.READ_COMMITTED, autocommit=True)
def task():
...
⚡ 异步
模型无需改动,异步场景使用 async_transactional 与 Model.async_query:
from sqlalchemy_db import SQLAlchemyDB, async_transactional
db = SQLAlchemyDB("sqlite+aiosqlite:///demo.db")
@async_transactional
async def main():
user = await User.async_query.get_by_id(1)
rows = await User.async_query.select(User.age >= 18)
page = await User.async_query.select_page(Page(page=1, page_size=20))
⚙️ 配置
db = SQLAlchemyDB({
"SQLALCHEMY_DATABASE_URI": "mysql+pymysql://root:123456@127.0.0.1:3306/demo",
"SQLALCHEMY_ECHO": False,
"SQLALCHEMY_ENGINE_OPTIONS": {"pool_size": 10, "pool_recycle": 3600},
"SQLALCHEMY_ASYNC_MODE": "auto", # auto / sync / async
"SNOWFLAKE_DATACENTER_ID": 1,
"SNOWFLAKE_WORKER_ID": 1,
})
| 配置项 | 说明 |
|---|---|
SQLALCHEMY_DATABASE_URI |
主库连接串 |
SQLALCHEMY_ENGINE_OPTIONS |
引擎参数 |
SQLALCHEMY_SESSION_OPTIONS |
Session 参数 |
SQLALCHEMY_ECHO |
打印 SQL |
SQLALCHEMY_ASYNC_MODE |
auto / sync / async |
SQLALCHEMY_SCHEMAS |
多数据源,{schema: url} |
SNOWFLAKE_DATACENTER_ID / SNOWFLAKE_WORKER_ID / SNOWFLAKE_EPOCH |
雪花 ID 配置 |
🔌 多数据源
from sqlalchemy_db import models
class Log(models.Model):
__tablename__ = "log"
__schema__ = "log" # 路由到 "log" 数据源
db = SQLAlchemyDB({
"SQLALCHEMY_DATABASE_URI": "mysql+pymysql://.../main",
"SQLALCHEMY_SCHEMAS": {"log": "mysql+pymysql://.../logs"},
})
🧩 Flask 集成
from flask import Flask
from sqlalchemy_db import SQLAlchemyDB
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "mysql+pymysql://root:123456@127.0.0.1:3306/demo"
db = SQLAlchemyDB(app)
@app.route("/users/<int:uid>")
def get_user(uid):
return db.session.get(User, uid).to_dict()
位于 Flask 应用上下文内时,Model.query 等入口会自动解析当前应用绑定的实例。
📚 示例
更多可运行示例见 examples/。
📄 许可
本项目基于 MIT 许可开源。
Metadata
Release files for pyre-sqlalchemy-db 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pyre_sqlalchemy_db-1.0.0.tar.gz | 35.1 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyre_sqlalchemy_db-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.6 kB
Release files / pyre_sqlalchemy_db-1.0.0.tar.gz
| Download URL | pyre_sqlalchemy_db-1.0.0.tar.gz |
|---|---|
| Size | 35.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
952c0234bbc19e0c2b855a83f2b4c4b93405f4a07c204366daf24059391e396f
|
|
BLAKE2b-256 checksum How to use checksums |
371799324d1098cd046b7a88e20fc557ca2d40076287f748ccf11ff3a7d7810a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / pyre_sqlalchemy_db-1.0.0-py3-none-any.whl
| Download URL | pyre_sqlalchemy_db-1.0.0-py3-none-any.whl |
|---|---|
| Size | 36.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dd3348894218bc89d2f9bb34266280a09648f5a875f1312ccf0c11f8cfd15a20
|
|
BLAKE2b-256 checksum How to use checksums |
dfb06ee464cf814c2bf7881559b42e7eeb1a60a25d84e996db9aa42cd305ce8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for pyre-sqlalchemy-db 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.