async-pybatis-orm


Nameasync-pybatis-orm JSON
Version 1.0.0 PyPI version JSON
download
home_pageNone
Summary一个基于 MySQL 异步场景,对齐 MyBatis-Plus 语法风格的 Python ORM 框架
upload_time2025-11-02 03:56:55
maintainerNone
docs_urlNone
authorlipop
requires_python>=3.8
licenseMIT
keywords async orm mysql database aiomysql asyncio mybatis-plus mapper crud query pagination
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # async-pybatis-orm

一个基于 MySQL 异步场景,对齐 MyBatis-Plus 语法风格的 Python ORM 框架。

专注于易用性与可扩展性,为从 Java MyBatis-Plus 转过来的开发者提供熟悉的 API。

## ✨ 特性

- 🚀 **异步支持**: 基于 asyncio 和 aiomysql,提供高性能异步操作
- 🎯 **MyBatis-Plus 风格**: 熟悉的 API 设计,降低学习成本
- 🔧 **灵活查询**: 链式条件构造器,支持复杂查询
- 📦 **完整 CRUD**: 提供 Insert、Update、Delete、Select 等完整操作
- 📄 **分页支持**: 内置分页功能,简单易用
- 🔒 **类型安全**: 支持 Python 类型注解

## 📦 安装

使用 pip 安装:

```bash
pip install async-pybatis-orm
```

或者从源码安装:

```bash
git clone https://github.com/lipop/async-pybatis-orm.git
cd async-pybatis-orm
pip install -e .
```

## 🚀 快速开始

### 1. 定义模型

```python
from datetime import datetime
from typing import Optional
from databases import Database
from async_pybatis_orm import CRUDModel, QueryWrapper
from async_pybatis_orm.base.database_manager import DatabaseAdapter
from async_pybatis_orm.fields import Field

# 定义数据库适配器
class DatabaseManager:
    _adapter: DatabaseAdapter = None

    @classmethod
    async def initialize(cls, database_url: str):
        database = Database(database_url)
        await database.connect()
        cls._adapter = DatabaseAdapter(database)
        return cls._adapter

# 定义模型
class User(CRUDModel):
    __table_meta__ = {"table_name": "users", "primary_key": "id"}

    id: int = Field(column_name="id")
    username: str = Field(column_name="user_name")
    email: Optional[str] = Field(column_name="email", nullable=True)
    age: Optional[int] = Field(column_name="age", nullable=True)
    status: str = Field(column_name="status", default="active")
    created_at: datetime = Field(column_name="created_at", default_factory=datetime.now)

    @classmethod
    async def _fetch_all(cls, sql: str, params: dict = None):
        cls._database = DatabaseManager._adapter
        return await cls._database.fetch_all(sql, params or {})

    @classmethod
    async def _execute(cls, sql: str, params):
        cls._database = DatabaseManager._adapter
        return await cls._database.execute(sql, params or {})
```

### 2. 初始化数据库连接

```python
import asyncio

async def init():
    db_url = "mysql+aiomysql://user:password@localhost:3306/dbname?min_size=5&max_size=20"
    await DatabaseManager.initialize(db_url)

asyncio.run(init())
```

### 3. 使用 CRUD 操作

```python
# 插入数据
user = User()
user.username = "test"
user.email = "test@example.com"
user.age = 18
await User.insert(user)

# 批量插入
users = [User(username=f"user{i}", age=20+i) for i in range(5)]
await User.batch_save(users)

# 查询数据
users = await User.select_list()
user = await User.select_by_id(1)
count = await User.select_count()

# 条件查询
wrapper = QueryWrapper().eq(User.username, "test").gt(User.age, 18)
users = await User.select_list(wrapper)

# 分页查询
from async_pybatis_orm.pagination import Page
page = Page(current=1, size=10)
result = await User.select_page(page)

# 更新数据
update_user = User()
update_user.id = 1
update_user.age = 25
await User.update_by_id(update_user)

# 条件更新
from async_pybatis_orm.wrapper import UpdateWrapper
await User.update_by_wrapper(
    UpdateWrapper()
    .eq(User.username, "test")
    .set(User.age, 25)
)

# 删除数据
await User.remove_by_id(1)

# 条件删除
wrapper = QueryWrapper().eq(User.status, "inactive")
await User.remove_by_wrapper(wrapper)
```

### 4. 链式查询

```python
# 复杂条件查询
wrapper = QueryWrapper() \
    .eq(User.status, "active") \
    .like(User.username, "admin") \
    .in_(User.age, [18, 19, 20]) \
    .between(User.created_at, "2023-01-01", "2023-12-31") \
    .order_by(User.id, desc=True) \
    .limit(10)

users = await User.select_list(wrapper)
```

## 📚 更多示例

查看 `example.py` 文件获取完整的测试示例。

## 🔧 开发

### 构建发布包

```bash
pip install build
python -m build
```

### 上传到 PyPI

```bash
pip install twine
twine upload dist/*
```

## 📄 许可证

MIT License

## 👤 作者

lipop

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "async-pybatis-orm",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "async, orm, mysql, database, aiomysql, asyncio, mybatis-plus, mapper, crud, query, pagination",
    "author": "lipop",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/64/02/2bfcdbad52f8f27644b912848cb8758fe307b86ac4662a71984f4ea0d5b4/async_pybatis_orm-1.0.0.tar.gz",
    "platform": null,
    "description": "# async-pybatis-orm\r\n\r\n\u4e00\u4e2a\u57fa\u4e8e MySQL \u5f02\u6b65\u573a\u666f\uff0c\u5bf9\u9f50 MyBatis-Plus \u8bed\u6cd5\u98ce\u683c\u7684 Python ORM \u6846\u67b6\u3002\r\n\r\n\u4e13\u6ce8\u4e8e\u6613\u7528\u6027\u4e0e\u53ef\u6269\u5c55\u6027\uff0c\u4e3a\u4ece Java MyBatis-Plus \u8f6c\u8fc7\u6765\u7684\u5f00\u53d1\u8005\u63d0\u4f9b\u719f\u6089\u7684 API\u3002\r\n\r\n## \u2728 \u7279\u6027\r\n\r\n- \ud83d\ude80 **\u5f02\u6b65\u652f\u6301**: \u57fa\u4e8e asyncio \u548c aiomysql\uff0c\u63d0\u4f9b\u9ad8\u6027\u80fd\u5f02\u6b65\u64cd\u4f5c\r\n- \ud83c\udfaf **MyBatis-Plus \u98ce\u683c**: \u719f\u6089\u7684 API \u8bbe\u8ba1\uff0c\u964d\u4f4e\u5b66\u4e60\u6210\u672c\r\n- \ud83d\udd27 **\u7075\u6d3b\u67e5\u8be2**: \u94fe\u5f0f\u6761\u4ef6\u6784\u9020\u5668\uff0c\u652f\u6301\u590d\u6742\u67e5\u8be2\r\n- \ud83d\udce6 **\u5b8c\u6574 CRUD**: \u63d0\u4f9b Insert\u3001Update\u3001Delete\u3001Select \u7b49\u5b8c\u6574\u64cd\u4f5c\r\n- \ud83d\udcc4 **\u5206\u9875\u652f\u6301**: \u5185\u7f6e\u5206\u9875\u529f\u80fd\uff0c\u7b80\u5355\u6613\u7528\r\n- \ud83d\udd12 **\u7c7b\u578b\u5b89\u5168**: \u652f\u6301 Python \u7c7b\u578b\u6ce8\u89e3\r\n\r\n## \ud83d\udce6 \u5b89\u88c5\r\n\r\n\u4f7f\u7528 pip \u5b89\u88c5\uff1a\r\n\r\n```bash\r\npip install async-pybatis-orm\r\n```\r\n\r\n\u6216\u8005\u4ece\u6e90\u7801\u5b89\u88c5\uff1a\r\n\r\n```bash\r\ngit clone https://github.com/lipop/async-pybatis-orm.git\r\ncd async-pybatis-orm\r\npip install -e .\r\n```\r\n\r\n## \ud83d\ude80 \u5feb\u901f\u5f00\u59cb\r\n\r\n### 1. \u5b9a\u4e49\u6a21\u578b\r\n\r\n```python\r\nfrom datetime import datetime\r\nfrom typing import Optional\r\nfrom databases import Database\r\nfrom async_pybatis_orm import CRUDModel, QueryWrapper\r\nfrom async_pybatis_orm.base.database_manager import DatabaseAdapter\r\nfrom async_pybatis_orm.fields import Field\r\n\r\n# \u5b9a\u4e49\u6570\u636e\u5e93\u9002\u914d\u5668\r\nclass DatabaseManager:\r\n    _adapter: DatabaseAdapter = None\r\n\r\n    @classmethod\r\n    async def initialize(cls, database_url: str):\r\n        database = Database(database_url)\r\n        await database.connect()\r\n        cls._adapter = DatabaseAdapter(database)\r\n        return cls._adapter\r\n\r\n# \u5b9a\u4e49\u6a21\u578b\r\nclass User(CRUDModel):\r\n    __table_meta__ = {\"table_name\": \"users\", \"primary_key\": \"id\"}\r\n\r\n    id: int = Field(column_name=\"id\")\r\n    username: str = Field(column_name=\"user_name\")\r\n    email: Optional[str] = Field(column_name=\"email\", nullable=True)\r\n    age: Optional[int] = Field(column_name=\"age\", nullable=True)\r\n    status: str = Field(column_name=\"status\", default=\"active\")\r\n    created_at: datetime = Field(column_name=\"created_at\", default_factory=datetime.now)\r\n\r\n    @classmethod\r\n    async def _fetch_all(cls, sql: str, params: dict = None):\r\n        cls._database = DatabaseManager._adapter\r\n        return await cls._database.fetch_all(sql, params or {})\r\n\r\n    @classmethod\r\n    async def _execute(cls, sql: str, params):\r\n        cls._database = DatabaseManager._adapter\r\n        return await cls._database.execute(sql, params or {})\r\n```\r\n\r\n### 2. \u521d\u59cb\u5316\u6570\u636e\u5e93\u8fde\u63a5\r\n\r\n```python\r\nimport asyncio\r\n\r\nasync def init():\r\n    db_url = \"mysql+aiomysql://user:password@localhost:3306/dbname?min_size=5&max_size=20\"\r\n    await DatabaseManager.initialize(db_url)\r\n\r\nasyncio.run(init())\r\n```\r\n\r\n### 3. \u4f7f\u7528 CRUD \u64cd\u4f5c\r\n\r\n```python\r\n# \u63d2\u5165\u6570\u636e\r\nuser = User()\r\nuser.username = \"test\"\r\nuser.email = \"test@example.com\"\r\nuser.age = 18\r\nawait User.insert(user)\r\n\r\n# \u6279\u91cf\u63d2\u5165\r\nusers = [User(username=f\"user{i}\", age=20+i) for i in range(5)]\r\nawait User.batch_save(users)\r\n\r\n# \u67e5\u8be2\u6570\u636e\r\nusers = await User.select_list()\r\nuser = await User.select_by_id(1)\r\ncount = await User.select_count()\r\n\r\n# \u6761\u4ef6\u67e5\u8be2\r\nwrapper = QueryWrapper().eq(User.username, \"test\").gt(User.age, 18)\r\nusers = await User.select_list(wrapper)\r\n\r\n# \u5206\u9875\u67e5\u8be2\r\nfrom async_pybatis_orm.pagination import Page\r\npage = Page(current=1, size=10)\r\nresult = await User.select_page(page)\r\n\r\n# \u66f4\u65b0\u6570\u636e\r\nupdate_user = User()\r\nupdate_user.id = 1\r\nupdate_user.age = 25\r\nawait User.update_by_id(update_user)\r\n\r\n# \u6761\u4ef6\u66f4\u65b0\r\nfrom async_pybatis_orm.wrapper import UpdateWrapper\r\nawait User.update_by_wrapper(\r\n    UpdateWrapper()\r\n    .eq(User.username, \"test\")\r\n    .set(User.age, 25)\r\n)\r\n\r\n# \u5220\u9664\u6570\u636e\r\nawait User.remove_by_id(1)\r\n\r\n# \u6761\u4ef6\u5220\u9664\r\nwrapper = QueryWrapper().eq(User.status, \"inactive\")\r\nawait User.remove_by_wrapper(wrapper)\r\n```\r\n\r\n### 4. \u94fe\u5f0f\u67e5\u8be2\r\n\r\n```python\r\n# \u590d\u6742\u6761\u4ef6\u67e5\u8be2\r\nwrapper = QueryWrapper() \\\r\n    .eq(User.status, \"active\") \\\r\n    .like(User.username, \"admin\") \\\r\n    .in_(User.age, [18, 19, 20]) \\\r\n    .between(User.created_at, \"2023-01-01\", \"2023-12-31\") \\\r\n    .order_by(User.id, desc=True) \\\r\n    .limit(10)\r\n\r\nusers = await User.select_list(wrapper)\r\n```\r\n\r\n## \ud83d\udcda \u66f4\u591a\u793a\u4f8b\r\n\r\n\u67e5\u770b `example.py` \u6587\u4ef6\u83b7\u53d6\u5b8c\u6574\u7684\u6d4b\u8bd5\u793a\u4f8b\u3002\r\n\r\n## \ud83d\udd27 \u5f00\u53d1\r\n\r\n### \u6784\u5efa\u53d1\u5e03\u5305\r\n\r\n```bash\r\npip install build\r\npython -m build\r\n```\r\n\r\n### \u4e0a\u4f20\u5230 PyPI\r\n\r\n```bash\r\npip install twine\r\ntwine upload dist/*\r\n```\r\n\r\n## \ud83d\udcc4 \u8bb8\u53ef\u8bc1\r\n\r\nMIT License\r\n\r\n## \ud83d\udc64 \u4f5c\u8005\r\n\r\nlipop\r\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u4e00\u4e2a\u57fa\u4e8e MySQL \u5f02\u6b65\u573a\u666f\uff0c\u5bf9\u9f50 MyBatis-Plus \u8bed\u6cd5\u98ce\u683c\u7684 Python ORM \u6846\u67b6",
    "version": "1.0.0",
    "project_urls": null,
    "split_keywords": [
        "async",
        " orm",
        " mysql",
        " database",
        " aiomysql",
        " asyncio",
        " mybatis-plus",
        " mapper",
        " crud",
        " query",
        " pagination"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "6a9f8e58630d3b3057f4b458a86483cce79064b8c36b79505b8996d9df11b471",
                "md5": "597b0389517d027e3fa790ca434505e5",
                "sha256": "ea58a219ed194210cab7045162dc46290d6906189c18621eb89f07309b36675d"
            },
            "downloads": -1,
            "filename": "async_pybatis_orm-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "597b0389517d027e3fa790ca434505e5",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 40133,
            "upload_time": "2025-11-02T03:56:53",
            "upload_time_iso_8601": "2025-11-02T03:56:53.989928Z",
            "url": "https://files.pythonhosted.org/packages/6a/9f/8e58630d3b3057f4b458a86483cce79064b8c36b79505b8996d9df11b471/async_pybatis_orm-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "64022bfcdbad52f8f27644b912848cb8758fe307b86ac4662a71984f4ea0d5b4",
                "md5": "7fa2f8fe740e021e66f42f16517d18e3",
                "sha256": "1c3a8a85e20256a1f4ce4eb978c83a4c47643e9c233b4a11d3f65ff35447f493"
            },
            "downloads": -1,
            "filename": "async_pybatis_orm-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "7fa2f8fe740e021e66f42f16517d18e3",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 26947,
            "upload_time": "2025-11-02T03:56:55",
            "upload_time_iso_8601": "2025-11-02T03:56:55.587040Z",
            "url": "https://files.pythonhosted.org/packages/64/02/2bfcdbad52f8f27644b912848cb8758fe307b86ac4662a71984f4ea0d5b4/async_pybatis_orm-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-11-02 03:56:55",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "async-pybatis-orm"
}
        
Elapsed time: 1.55878s