very-nb-api


Namevery-nb-api JSON
Version 0.7 PyPI version JSON
download
home_pagehttps://github.com/your-username/nb_api
Summary基于 FastAPI + Pydantic v2 + SQLModel 的自动 CRUD 路由生成框架
upload_time2025-10-24 10:18:05
maintainerNone
docs_urlNone
authorNB API Team
requires_python>=3.9
licenseNone
keywords fastapi crud rest api sqlmodel pydantic router
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # nb_api

<p align="center">
  <!-- 你可以在这里放一个酷炫的 Logo -->
  <!-- <img src="path/to/your/logo.png" height="200" /> -->
</p>
<p align="center">
  <em>⚡️ 为你的数据模型闪电般地生成 CRUD API ⚡️</em>
</p>
<p align="center">
  <!-- 在这里可以添加一些徽章,比如 PyPI 版本、构建状态等 -->
  <img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/nb_api">
  <img alt="License" src="https://img.shields.io/github/license/ydf0509/nb_api">
</p>

---

## 🚀 `nb_api` 是什么?

`nb_api` 是一个为现代 FastAPI 应用量身打造的 **CRUD 路由自动生成框架**。你只需定义好你的数据模型,`nb_api` 就能为你自动创建一整套完整、健壮且文档齐全的增、删、改、查(CRUD)API 接口。

`nb_api` 旨在解决为 FastAPI 应用重复编写 CRUD 接口的痛点。它支持多种数据存储后端,提供了更强大、更现代化的功能。

## ✨ 核心优势

- **多数据库支持**: 支持 **SQLModel**、**SQLAlchemy**、**Tortoise ORM** 和 **内存存储**,满足不同场景需求
- **现代化技术栈**: 完全基于 **FastAPI** + **Pydantic v2** 构建,享受最新的性能优化和最完善的类型提示
- **高度自动化**: 告别重复编写 CRUD 样板代码,让你专注于核心业务逻辑
- **强大的搜索能力**: 内置"超级搜索"接口,允许前端通过 JSON 动态构建复杂的过滤和排序查询
- **规范的 API 设计**: 所有响应都封装在统一的 `ResponseModel` 中,无论是成功还是失败,都有一致的结构,极大简化了前端处理
- **生产级特性**: 开箱即用的分页、依赖注入、慢请求日志记录等功能,让你的应用兼具开发效率和生产环境下的可观测性
- **灵活可扩展**: 轻松禁用、覆盖默认路由,或添加自定义路由,满足你的所有特殊需求

## 🛠️ 安装

```bash
pip install very_nb_api fastapi sqlmodel uvicorn
```

**注意安装和实际导入不同,因为提示nb_api这个名字和pypi已存在的包相似冲突了**
#### 安装
```
pip install very_nb_api
```

#### 导入
```
import nb_api
```

## 快速开始

### SQLModel 版本

在短短十几行代码内,即可拥有一个功能完备的 CRUD API。

```python
# main.py
from typing import Optional
from sqlmodel import Field, Session, SQLModel, create_engine
from fastapi import FastAPI
from nb_api import SQLModelCRUDRouter

# 1. 定义 SQLModel 模型
class Book(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str
    author: str

# 2. 设置数据库
engine = create_engine("sqlite:///database.db")

def get_session():
    with Session(engine) as session:
        yield session

# 3. 创建 FastAPI 应用和 nb_api 路由
app = FastAPI()

@app.on_event("startup")
def on_startup():
    SQLModel.metadata.create_all(engine)

# 核心用法!
app.include_router(
    SQLModelCRUDRouter(schema=Book, db_model=Book, db_session=get_session)
)
```

### 异步 SQLModel 版本

```python
# main.py
from typing import Optional, AsyncGenerator
from sqlmodel import Field, SQLModel
from sqlalchemy.ext.asyncio import create_async_engine
from sqlmodel.ext.asyncio.session import AsyncSession
from fastapi import FastAPI
from nb_api import AioSQLModelCRUDRouter

# 1. 定义 SQLModel 模型
class Book(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str
    author: str

# 2. 设置异步数据库
DATABASE_URL = "sqlite+aiosqlite:///database.db"
engine = create_async_engine(DATABASE_URL)

async def get_session() -> AsyncGenerator[AsyncSession, None]:
    async with AsyncSession(engine) as session:
        yield session

# 3. 创建 FastAPI 应用和 nb_api 路由
app = FastAPI()

# 核心用法!
app.include_router(
    AioSQLModelCRUDRouter(schema=Book, db_model=Book, db=get_session)
)
```

### Tortoise ORM 版本

```python
# main.py
from typing import Optional
from tortoise.models import Model
from tortoise import fields
from tortoise.contrib.fastapi import register_tortoise
from fastapi import FastAPI
from pydantic import BaseModel
from nb_api import TortoiseCRUDRouter

# 1. 定义 Tortoise ORM 模型
class Book(Model):
    id = fields.IntField(pk=True)
    title = fields.CharField(max_length=100)
    author = fields.CharField(max_length=100)

# 2. 定义 Pydantic 模型
class BookSchema(BaseModel):
    id: int
    title: str
    author: str

    class Config:
        from_attributes = True

# 3. 创建 FastAPI 应用
app = FastAPI()

# 4. 注册 Tortoise ORM
register_tortoise(
    app,
    db_url="sqlite://db.sqlite3",
    modules={"models": ["__main__"]},
    generate_schemas=True,
    add_exception_handlers=True
)

# 核心用法!
app.include_router(
    TortoiseCRUDRouter(schema=BookSchema, db_model=Book, prefix="books")
)
```

### 内存版本(无需数据库)

```python
# main.py
from typing import Optional
from pydantic import BaseModel
from fastapi import FastAPI
from nb_api import MemoryCRUDRouter

# 1. 定义 Pydantic 模型
class Book(BaseModel):
    id: Optional[int] = None
    title: str
    author: str

# 2. 创建 FastAPI 应用
app = FastAPI()

# 核心用法!
app.include_router(
    MemoryCRUDRouter(schema=Book, prefix="books")
)
```

启动应用 `uvicorn main:app --reload`,然后访问 `http://127.0.0.1:8000/docs`,你将看到 `nb_api` 为 `Book` 模型自动生成的所有接口!

## 🌟 功能展示

### 1. 自动生成的 CRUD 路由

| 路由 | 方法 | 描述 |
|---|---|---|
| `/book` | `GET` | 获取所有书籍 (支持分页) |
| `/book` | `POST` | 创建一本新书 |
| `/book` | `DELETE` | 删除所有书籍 |
| `/book/{item_id}` | `GET` | 获取指定 ID 的书籍 |
| `/book/{item_id}` | `PUT` | 更新指定 ID 的书籍 |
| `/book/{item_id}` | `DELETE` | 删除指定 ID 的书籍 |
| `/book/search` | `POST` | **超级搜索接口** |

### 2. 超级搜索接口 (`/search`)

这是 `nb_api` 的独有功能!通过一个 `POST` 请求,实现复杂的动态查询。

**请求**: `POST /book/search`
**请求体**:
```json
{
  "filters": [
    { "field": "author", "operator": "contains", "value": "Tolkien" },
    { "field": "id", "operator": "in", "value": [1, 3, 5] }
  ],
  "sorting": [
    { "field": "title", "direction": "asc" }
  ]
}
```

### 3. 统一的 API 响应

**成功响应**:
```json
{
  "status_code": 0,
  "msg": "success",
  "data": { "id": 1, "title": "The Hobbit", "author": "J.R.R. Tolkien" }
}
```

**错误响应**:
```json
{
  "status_code": 404,
  "msg": "Item not found"
}
```

### 4. 路由定制与扩展

`nb_api` 提供了丰富的初始化参数来定制路由行为。

```python
from fastapi import Depends

router = SQLModelCRUDRouter(
    schema=Book,
    db_model=Book,
    db_session=get_session,
    
    # --- 功能配置 ---
    paginate=50,                  # 设置分页最大数量

    
    # --- 路由控制 ---
    prefix="my-books",            # 自定义路由前缀
    tags=["图书管理"],            # 自定义 OpenAPI 标签
    delete_all_route=False,       # 禁用"删除所有"路由
    
    # --- 依赖注入 (权限控制) ---
    update_route=[Depends(require_admin_user)],
    create_route=[Depends(require_login)]
)
```

你也可以像使用普通的 `APIRouter` 一样,轻松地覆盖或添加新路由。

```python
# 覆盖默认的 get_one 路由
@router.get("/{item_id}")
def custom_get_one(item_id: int):
    return {"message": f"You are viewing book {item_id} with a custom route!"}

# 添加一个全新的路由
@router.post("/{item_id}/publish")
def publish_book(item_id: int):
    # ... 发布逻辑 ...
    return {"message": "Book published!"}
```


### 5 一个接口没写,下面都是nb_api自动生成的接口

接口文档截图:
[![pVXA2ZD.png](https://s21.ax1x.com/2025/10/23/pVXA2ZD.png)](https://imgchr.com/i/pVXA2ZD)

这些接口都是nb_api自动生成的,你只需要定义好你的数据模型,nb_api就会自动生成这些接口,全部都不是人工手写def 的 fastapi 接口

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/your-username/nb_api",
    "name": "very-nb-api",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "fastapi crud rest api sqlmodel pydantic router",
    "author": "NB API Team",
    "author_email": "ydf0509@example.com",
    "download_url": "https://files.pythonhosted.org/packages/27/e7/cd58d76f1dc14f2fd11b9a5dd20dc13af04dd5c029daea8a0be36ce71de8/very_nb_api-0.7.tar.gz",
    "platform": null,
    "description": "# nb_api\r\n\r\n<p align=\"center\">\r\n  <!-- \u4f60\u53ef\u4ee5\u5728\u8fd9\u91cc\u653e\u4e00\u4e2a\u9177\u70ab\u7684 Logo -->\r\n  <!-- <img src=\"path/to/your/logo.png\" height=\"200\" /> -->\r\n</p>\r\n<p align=\"center\">\r\n  <em>\u26a1\ufe0f \u4e3a\u4f60\u7684\u6570\u636e\u6a21\u578b\u95ea\u7535\u822c\u5730\u751f\u6210 CRUD API \u26a1\ufe0f</em>\r\n</p>\r\n<p align=\"center\">\r\n  <!-- \u5728\u8fd9\u91cc\u53ef\u4ee5\u6dfb\u52a0\u4e00\u4e9b\u5fbd\u7ae0\uff0c\u6bd4\u5982 PyPI \u7248\u672c\u3001\u6784\u5efa\u72b6\u6001\u7b49 -->\r\n  <img alt=\"PyPI - Python Version\" src=\"https://img.shields.io/pypi/pyversions/nb_api\">\r\n  <img alt=\"License\" src=\"https://img.shields.io/github/license/ydf0509/nb_api\">\r\n</p>\r\n\r\n---\r\n\r\n## \ud83d\ude80 `nb_api` \u662f\u4ec0\u4e48\uff1f\r\n\r\n`nb_api` \u662f\u4e00\u4e2a\u4e3a\u73b0\u4ee3 FastAPI \u5e94\u7528\u91cf\u8eab\u6253\u9020\u7684 **CRUD \u8def\u7531\u81ea\u52a8\u751f\u6210\u6846\u67b6**\u3002\u4f60\u53ea\u9700\u5b9a\u4e49\u597d\u4f60\u7684\u6570\u636e\u6a21\u578b\uff0c`nb_api` \u5c31\u80fd\u4e3a\u4f60\u81ea\u52a8\u521b\u5efa\u4e00\u6574\u5957\u5b8c\u6574\u3001\u5065\u58ee\u4e14\u6587\u6863\u9f50\u5168\u7684\u589e\u3001\u5220\u3001\u6539\u3001\u67e5\uff08CRUD\uff09API \u63a5\u53e3\u3002\r\n\r\n`nb_api` \u65e8\u5728\u89e3\u51b3\u4e3a FastAPI \u5e94\u7528\u91cd\u590d\u7f16\u5199 CRUD \u63a5\u53e3\u7684\u75db\u70b9\u3002\u5b83\u652f\u6301\u591a\u79cd\u6570\u636e\u5b58\u50a8\u540e\u7aef\uff0c\u63d0\u4f9b\u4e86\u66f4\u5f3a\u5927\u3001\u66f4\u73b0\u4ee3\u5316\u7684\u529f\u80fd\u3002\r\n\r\n## \u2728 \u6838\u5fc3\u4f18\u52bf\r\n\r\n- **\u591a\u6570\u636e\u5e93\u652f\u6301**: \u652f\u6301 **SQLModel**\u3001**SQLAlchemy**\u3001**Tortoise ORM** \u548c **\u5185\u5b58\u5b58\u50a8**\uff0c\u6ee1\u8db3\u4e0d\u540c\u573a\u666f\u9700\u6c42\r\n- **\u73b0\u4ee3\u5316\u6280\u672f\u6808**: \u5b8c\u5168\u57fa\u4e8e **FastAPI** + **Pydantic v2** \u6784\u5efa\uff0c\u4eab\u53d7\u6700\u65b0\u7684\u6027\u80fd\u4f18\u5316\u548c\u6700\u5b8c\u5584\u7684\u7c7b\u578b\u63d0\u793a\r\n- **\u9ad8\u5ea6\u81ea\u52a8\u5316**: \u544a\u522b\u91cd\u590d\u7f16\u5199 CRUD \u6837\u677f\u4ee3\u7801\uff0c\u8ba9\u4f60\u4e13\u6ce8\u4e8e\u6838\u5fc3\u4e1a\u52a1\u903b\u8f91\r\n- **\u5f3a\u5927\u7684\u641c\u7d22\u80fd\u529b**: \u5185\u7f6e\"\u8d85\u7ea7\u641c\u7d22\"\u63a5\u53e3\uff0c\u5141\u8bb8\u524d\u7aef\u901a\u8fc7 JSON \u52a8\u6001\u6784\u5efa\u590d\u6742\u7684\u8fc7\u6ee4\u548c\u6392\u5e8f\u67e5\u8be2\r\n- **\u89c4\u8303\u7684 API \u8bbe\u8ba1**: \u6240\u6709\u54cd\u5e94\u90fd\u5c01\u88c5\u5728\u7edf\u4e00\u7684 `ResponseModel` \u4e2d\uff0c\u65e0\u8bba\u662f\u6210\u529f\u8fd8\u662f\u5931\u8d25\uff0c\u90fd\u6709\u4e00\u81f4\u7684\u7ed3\u6784\uff0c\u6781\u5927\u7b80\u5316\u4e86\u524d\u7aef\u5904\u7406\r\n- **\u751f\u4ea7\u7ea7\u7279\u6027**: \u5f00\u7bb1\u5373\u7528\u7684\u5206\u9875\u3001\u4f9d\u8d56\u6ce8\u5165\u3001\u6162\u8bf7\u6c42\u65e5\u5fd7\u8bb0\u5f55\u7b49\u529f\u80fd\uff0c\u8ba9\u4f60\u7684\u5e94\u7528\u517c\u5177\u5f00\u53d1\u6548\u7387\u548c\u751f\u4ea7\u73af\u5883\u4e0b\u7684\u53ef\u89c2\u6d4b\u6027\r\n- **\u7075\u6d3b\u53ef\u6269\u5c55**: \u8f7b\u677e\u7981\u7528\u3001\u8986\u76d6\u9ed8\u8ba4\u8def\u7531\uff0c\u6216\u6dfb\u52a0\u81ea\u5b9a\u4e49\u8def\u7531\uff0c\u6ee1\u8db3\u4f60\u7684\u6240\u6709\u7279\u6b8a\u9700\u6c42\r\n\r\n## \ud83d\udee0\ufe0f \u5b89\u88c5\r\n\r\n```bash\r\npip install very_nb_api fastapi sqlmodel uvicorn\r\n```\r\n\r\n**\u6ce8\u610f\u5b89\u88c5\u548c\u5b9e\u9645\u5bfc\u5165\u4e0d\u540c,\u56e0\u4e3a\u63d0\u793anb_api\u8fd9\u4e2a\u540d\u5b57\u548cpypi\u5df2\u5b58\u5728\u7684\u5305\u76f8\u4f3c\u51b2\u7a81\u4e86**\r\n#### \u5b89\u88c5\r\n```\r\npip install very_nb_api\r\n```\r\n\r\n#### \u5bfc\u5165\r\n```\r\nimport nb_api\r\n```\r\n\r\n## \u5feb\u901f\u5f00\u59cb\r\n\r\n### SQLModel \u7248\u672c\r\n\r\n\u5728\u77ed\u77ed\u5341\u51e0\u884c\u4ee3\u7801\u5185\uff0c\u5373\u53ef\u62e5\u6709\u4e00\u4e2a\u529f\u80fd\u5b8c\u5907\u7684 CRUD API\u3002\r\n\r\n```python\r\n# main.py\r\nfrom typing import Optional\r\nfrom sqlmodel import Field, Session, SQLModel, create_engine\r\nfrom fastapi import FastAPI\r\nfrom nb_api import SQLModelCRUDRouter\r\n\r\n# 1. \u5b9a\u4e49 SQLModel \u6a21\u578b\r\nclass Book(SQLModel, table=True):\r\n    id: Optional[int] = Field(default=None, primary_key=True)\r\n    title: str\r\n    author: str\r\n\r\n# 2. \u8bbe\u7f6e\u6570\u636e\u5e93\r\nengine = create_engine(\"sqlite:///database.db\")\r\n\r\ndef get_session():\r\n    with Session(engine) as session:\r\n        yield session\r\n\r\n# 3. \u521b\u5efa FastAPI \u5e94\u7528\u548c nb_api \u8def\u7531\r\napp = FastAPI()\r\n\r\n@app.on_event(\"startup\")\r\ndef on_startup():\r\n    SQLModel.metadata.create_all(engine)\r\n\r\n# \u6838\u5fc3\u7528\u6cd5\uff01\r\napp.include_router(\r\n    SQLModelCRUDRouter(schema=Book, db_model=Book, db_session=get_session)\r\n)\r\n```\r\n\r\n### \u5f02\u6b65 SQLModel \u7248\u672c\r\n\r\n```python\r\n# main.py\r\nfrom typing import Optional, AsyncGenerator\r\nfrom sqlmodel import Field, SQLModel\r\nfrom sqlalchemy.ext.asyncio import create_async_engine\r\nfrom sqlmodel.ext.asyncio.session import AsyncSession\r\nfrom fastapi import FastAPI\r\nfrom nb_api import AioSQLModelCRUDRouter\r\n\r\n# 1. \u5b9a\u4e49 SQLModel \u6a21\u578b\r\nclass Book(SQLModel, table=True):\r\n    id: Optional[int] = Field(default=None, primary_key=True)\r\n    title: str\r\n    author: str\r\n\r\n# 2. \u8bbe\u7f6e\u5f02\u6b65\u6570\u636e\u5e93\r\nDATABASE_URL = \"sqlite+aiosqlite:///database.db\"\r\nengine = create_async_engine(DATABASE_URL)\r\n\r\nasync def get_session() -> AsyncGenerator[AsyncSession, None]:\r\n    async with AsyncSession(engine) as session:\r\n        yield session\r\n\r\n# 3. \u521b\u5efa FastAPI \u5e94\u7528\u548c nb_api \u8def\u7531\r\napp = FastAPI()\r\n\r\n# \u6838\u5fc3\u7528\u6cd5\uff01\r\napp.include_router(\r\n    AioSQLModelCRUDRouter(schema=Book, db_model=Book, db=get_session)\r\n)\r\n```\r\n\r\n### Tortoise ORM \u7248\u672c\r\n\r\n```python\r\n# main.py\r\nfrom typing import Optional\r\nfrom tortoise.models import Model\r\nfrom tortoise import fields\r\nfrom tortoise.contrib.fastapi import register_tortoise\r\nfrom fastapi import FastAPI\r\nfrom pydantic import BaseModel\r\nfrom nb_api import TortoiseCRUDRouter\r\n\r\n# 1. \u5b9a\u4e49 Tortoise ORM \u6a21\u578b\r\nclass Book(Model):\r\n    id = fields.IntField(pk=True)\r\n    title = fields.CharField(max_length=100)\r\n    author = fields.CharField(max_length=100)\r\n\r\n# 2. \u5b9a\u4e49 Pydantic \u6a21\u578b\r\nclass BookSchema(BaseModel):\r\n    id: int\r\n    title: str\r\n    author: str\r\n\r\n    class Config:\r\n        from_attributes = True\r\n\r\n# 3. \u521b\u5efa FastAPI \u5e94\u7528\r\napp = FastAPI()\r\n\r\n# 4. \u6ce8\u518c Tortoise ORM\r\nregister_tortoise(\r\n    app,\r\n    db_url=\"sqlite://db.sqlite3\",\r\n    modules={\"models\": [\"__main__\"]},\r\n    generate_schemas=True,\r\n    add_exception_handlers=True\r\n)\r\n\r\n# \u6838\u5fc3\u7528\u6cd5\uff01\r\napp.include_router(\r\n    TortoiseCRUDRouter(schema=BookSchema, db_model=Book, prefix=\"books\")\r\n)\r\n```\r\n\r\n### \u5185\u5b58\u7248\u672c\uff08\u65e0\u9700\u6570\u636e\u5e93\uff09\r\n\r\n```python\r\n# main.py\r\nfrom typing import Optional\r\nfrom pydantic import BaseModel\r\nfrom fastapi import FastAPI\r\nfrom nb_api import MemoryCRUDRouter\r\n\r\n# 1. \u5b9a\u4e49 Pydantic \u6a21\u578b\r\nclass Book(BaseModel):\r\n    id: Optional[int] = None\r\n    title: str\r\n    author: str\r\n\r\n# 2. \u521b\u5efa FastAPI \u5e94\u7528\r\napp = FastAPI()\r\n\r\n# \u6838\u5fc3\u7528\u6cd5\uff01\r\napp.include_router(\r\n    MemoryCRUDRouter(schema=Book, prefix=\"books\")\r\n)\r\n```\r\n\r\n\u542f\u52a8\u5e94\u7528 `uvicorn main:app --reload`\uff0c\u7136\u540e\u8bbf\u95ee `http://127.0.0.1:8000/docs`\uff0c\u4f60\u5c06\u770b\u5230 `nb_api` \u4e3a `Book` \u6a21\u578b\u81ea\u52a8\u751f\u6210\u7684\u6240\u6709\u63a5\u53e3\uff01\r\n\r\n## \ud83c\udf1f \u529f\u80fd\u5c55\u793a\r\n\r\n### 1. \u81ea\u52a8\u751f\u6210\u7684 CRUD \u8def\u7531\r\n\r\n| \u8def\u7531 | \u65b9\u6cd5 | \u63cf\u8ff0 |\r\n|---|---|---|\r\n| `/book` | `GET` | \u83b7\u53d6\u6240\u6709\u4e66\u7c4d (\u652f\u6301\u5206\u9875) |\r\n| `/book` | `POST` | \u521b\u5efa\u4e00\u672c\u65b0\u4e66 |\r\n| `/book` | `DELETE` | \u5220\u9664\u6240\u6709\u4e66\u7c4d |\r\n| `/book/{item_id}` | `GET` | \u83b7\u53d6\u6307\u5b9a ID \u7684\u4e66\u7c4d |\r\n| `/book/{item_id}` | `PUT` | \u66f4\u65b0\u6307\u5b9a ID \u7684\u4e66\u7c4d |\r\n| `/book/{item_id}` | `DELETE` | \u5220\u9664\u6307\u5b9a ID \u7684\u4e66\u7c4d |\r\n| `/book/search` | `POST` | **\u8d85\u7ea7\u641c\u7d22\u63a5\u53e3** |\r\n\r\n### 2. \u8d85\u7ea7\u641c\u7d22\u63a5\u53e3 (`/search`)\r\n\r\n\u8fd9\u662f `nb_api` \u7684\u72ec\u6709\u529f\u80fd\uff01\u901a\u8fc7\u4e00\u4e2a `POST` \u8bf7\u6c42\uff0c\u5b9e\u73b0\u590d\u6742\u7684\u52a8\u6001\u67e5\u8be2\u3002\r\n\r\n**\u8bf7\u6c42**: `POST /book/search`\r\n**\u8bf7\u6c42\u4f53**:\r\n```json\r\n{\r\n  \"filters\": [\r\n    { \"field\": \"author\", \"operator\": \"contains\", \"value\": \"Tolkien\" },\r\n    { \"field\": \"id\", \"operator\": \"in\", \"value\": [1, 3, 5] }\r\n  ],\r\n  \"sorting\": [\r\n    { \"field\": \"title\", \"direction\": \"asc\" }\r\n  ]\r\n}\r\n```\r\n\r\n### 3. \u7edf\u4e00\u7684 API \u54cd\u5e94\r\n\r\n**\u6210\u529f\u54cd\u5e94**:\r\n```json\r\n{\r\n  \"status_code\": 0,\r\n  \"msg\": \"success\",\r\n  \"data\": { \"id\": 1, \"title\": \"The Hobbit\", \"author\": \"J.R.R. Tolkien\" }\r\n}\r\n```\r\n\r\n**\u9519\u8bef\u54cd\u5e94**:\r\n```json\r\n{\r\n  \"status_code\": 404,\r\n  \"msg\": \"Item not found\"\r\n}\r\n```\r\n\r\n### 4. \u8def\u7531\u5b9a\u5236\u4e0e\u6269\u5c55\r\n\r\n`nb_api` \u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u521d\u59cb\u5316\u53c2\u6570\u6765\u5b9a\u5236\u8def\u7531\u884c\u4e3a\u3002\r\n\r\n```python\r\nfrom fastapi import Depends\r\n\r\nrouter = SQLModelCRUDRouter(\r\n    schema=Book,\r\n    db_model=Book,\r\n    db_session=get_session,\r\n    \r\n    # --- \u529f\u80fd\u914d\u7f6e ---\r\n    paginate=50,                  # \u8bbe\u7f6e\u5206\u9875\u6700\u5927\u6570\u91cf\r\n\r\n    \r\n    # --- \u8def\u7531\u63a7\u5236 ---\r\n    prefix=\"my-books\",            # \u81ea\u5b9a\u4e49\u8def\u7531\u524d\u7f00\r\n    tags=[\"\u56fe\u4e66\u7ba1\u7406\"],            # \u81ea\u5b9a\u4e49 OpenAPI \u6807\u7b7e\r\n    delete_all_route=False,       # \u7981\u7528\"\u5220\u9664\u6240\u6709\"\u8def\u7531\r\n    \r\n    # --- \u4f9d\u8d56\u6ce8\u5165 (\u6743\u9650\u63a7\u5236) ---\r\n    update_route=[Depends(require_admin_user)],\r\n    create_route=[Depends(require_login)]\r\n)\r\n```\r\n\r\n\u4f60\u4e5f\u53ef\u4ee5\u50cf\u4f7f\u7528\u666e\u901a\u7684 `APIRouter` \u4e00\u6837\uff0c\u8f7b\u677e\u5730\u8986\u76d6\u6216\u6dfb\u52a0\u65b0\u8def\u7531\u3002\r\n\r\n```python\r\n# \u8986\u76d6\u9ed8\u8ba4\u7684 get_one \u8def\u7531\r\n@router.get(\"/{item_id}\")\r\ndef custom_get_one(item_id: int):\r\n    return {\"message\": f\"You are viewing book {item_id} with a custom route!\"}\r\n\r\n# \u6dfb\u52a0\u4e00\u4e2a\u5168\u65b0\u7684\u8def\u7531\r\n@router.post(\"/{item_id}/publish\")\r\ndef publish_book(item_id: int):\r\n    # ... \u53d1\u5e03\u903b\u8f91 ...\r\n    return {\"message\": \"Book published!\"}\r\n```\r\n\r\n\r\n### 5 \u4e00\u4e2a\u63a5\u53e3\u6ca1\u5199,\u4e0b\u9762\u90fd\u662fnb_api\u81ea\u52a8\u751f\u6210\u7684\u63a5\u53e3\r\n\r\n\u63a5\u53e3\u6587\u6863\u622a\u56fe:\r\n[![pVXA2ZD.png](https://s21.ax1x.com/2025/10/23/pVXA2ZD.png)](https://imgchr.com/i/pVXA2ZD)\r\n\r\n\u8fd9\u4e9b\u63a5\u53e3\u90fd\u662fnb_api\u81ea\u52a8\u751f\u6210\u7684,\u4f60\u53ea\u9700\u8981\u5b9a\u4e49\u597d\u4f60\u7684\u6570\u636e\u6a21\u578b,nb_api\u5c31\u4f1a\u81ea\u52a8\u751f\u6210\u8fd9\u4e9b\u63a5\u53e3,\u5168\u90e8\u90fd\u4e0d\u662f\u4eba\u5de5\u624b\u5199def \u7684 fastapi \u63a5\u53e3\r\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "\u57fa\u4e8e FastAPI + Pydantic v2 + SQLModel \u7684\u81ea\u52a8 CRUD \u8def\u7531\u751f\u6210\u6846\u67b6",
    "version": "0.7",
    "project_urls": {
        "Homepage": "https://github.com/your-username/nb_api"
    },
    "split_keywords": [
        "fastapi",
        "crud",
        "rest",
        "api",
        "sqlmodel",
        "pydantic",
        "router"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "131cf13409e384948fb179b4e3ee7d9181ff3f7ee5880b7ccd218e9add8b3dec",
                "md5": "9ab13f4261dcaec3abb4190f50ffc6dd",
                "sha256": "7b292d509b69509a88e01f4c896434ca7ff6be60c3794de166a401e5b9a92eb3"
            },
            "downloads": -1,
            "filename": "very_nb_api-0.7-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "9ab13f4261dcaec3abb4190f50ffc6dd",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 23298,
            "upload_time": "2025-10-24T10:18:04",
            "upload_time_iso_8601": "2025-10-24T10:18:04.010727Z",
            "url": "https://files.pythonhosted.org/packages/13/1c/f13409e384948fb179b4e3ee7d9181ff3f7ee5880b7ccd218e9add8b3dec/very_nb_api-0.7-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "27e7cd58d76f1dc14f2fd11b9a5dd20dc13af04dd5c029daea8a0be36ce71de8",
                "md5": "ace50ce66275d246ef89efa02a14c272",
                "sha256": "52e31de22aa4cdb189ab1f049d008a9ef93dcbce1ea021af7a017f166682b84b"
            },
            "downloads": -1,
            "filename": "very_nb_api-0.7.tar.gz",
            "has_sig": false,
            "md5_digest": "ace50ce66275d246ef89efa02a14c272",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 19571,
            "upload_time": "2025-10-24T10:18:05",
            "upload_time_iso_8601": "2025-10-24T10:18:05.829952Z",
            "url": "https://files.pythonhosted.org/packages/27/e7/cd58d76f1dc14f2fd11b9a5dd20dc13af04dd5c029daea8a0be36ce71de8/very_nb_api-0.7.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-24 10:18:05",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "your-username",
    "github_project": "nb_api",
    "github_not_found": true,
    "lcname": "very-nb-api"
}
        
Elapsed time: 2.52599s