Python小酷库系列:pyNest,把FastAPI程序写出Spring的味道

pyNest,把FastAPI程序写出Spring的风格

    • 快速入门
      • 1、安装pyNest
      • 2、创建项目
      • 3、编写app_module.py
      • 4、编写app_service.py
      • 5、编写app_controller.py
      • 6、编写main.py
      • 7、启动程序
    • 核心概念
      • 1、Modules
      • 2、Controllers
      • 3、Providers
      • 4、ORM Provider

NestJS是风靡于Node.js圈的web框架,它深度借鉴了Spring Boot的设计思路,但又比Spring Boot小巧灵活。
对于转战于python圈的小伙伴来说,如果可以把Spring Boot搬运到python,那将是一件非常有价值的事情,于是就有了pyNest这个“小酷库”——它站在FastAPI的基础,在python中实现了NestJS风格,让你的代码有了Spring的味道。本文我们就一起来试试pyNest这个“小酷库”。

快速入门

1、安装pyNest

pip install pynest-api

2、创建项目

my_pynest_project/
├── src/
│   ├── __init__.py
│   ├── app_module.py
│   ├── app_controller.py
│   ├── app_service.py
├── main.py
├── requirements.txt
└── README.md

3、编写app_module.py

from nest.core import Module, PyNestFactory
from .app_controller import AppController
from .app_service import AppService@Module(controllers=[AppController],providers=[AppService],
)
class AppModule:passapp = PyNestFactory.create(AppModule,description="This is my PyNest app",title="My App",version="1.0.0",debug=True,
)http_server = app.get_server()

4、编写app_service.py

from nest.core import Injectable@Injectable
class AppService:def __init__(self):self.app_name = "MyApp"self.app_version = "1.0.0"def get_app_info(self):return {"app_name": self.app_name, "app_version": self.app_version}

5、编写app_controller.py

from nest.core import Controller, Get
from .app_service import AppService@Controller("/")
class AppController:def __init__(self, service: AppService):self.service = service@Get("/")def get_app_info(self):return self.service.get_app_info()

6、编写main.py

import uvicorn
from src.app_module import http_serverif __name__ == "__main__":uvicorn.run(http_server, host="0.0.0.0", port=8000, reload=True)

7、启动程序

python main.py

核心概念

PyNest 主要包括Modules、Controllers、Providers三个核心概念,其中:

  • Module负责组织和管理 ControllerProvider
  • Controller 负责接收请求,调用注入的 Provider 来完成业务逻辑
  • Provider服务/工具,也可以互相注入组合;
  • 模块之间通过 imports/exports 连接起来,实现模块解耦和共享。

它们的关系如下图:

Product
Order
User
Exports
Imports
Exports
Imports
ProductController
ProductModule
ProductService
OrderController
OrderModule
OrderService
AuthController
UserModule
UserController
UserService
AuthService
HTTP Request
FastAPI APP

1、Modules

模块(Modules)是一个带有@Module()装饰器注解的类。@Module()装饰器提供 PyNest 用于组织应用程序结构的元数据。
在pyNest中,每个应用程序至少有一个模块,即根模块。根模块是 PyNest 构建应用程序图的起点,而应用程序图是 PyNest 用于解析模块和提供程序关系及依赖关系的内部数据结构。虽然非常小的应用程序理论上可能只有一个根模块,但这并不是典型情况。强烈建议使用模块作为组织组件的有效方法。
模块定义了以下元数据:

  • controllers:控制器列表
  • providers:服务提供者(通常是业务逻辑)
  • imports:导入其他模块
  • exports:暴露自己的部分 provider 给其他模块使用

2、Controllers

控制器(Controllers )是一个带有@Controller() 装饰器注解的类。该类负责处理传入的请求并向客户端返回响应。控制器在应用程序中注册路由并管理请求和响应对象,有效地充当客户端与应用程序交互的网关。
pyNest 支持 5 种 http 方法——Get、Post、Put、Delete、Patch。由于 Pynest 是 FastAPI 的抽象,因此我们可以像在 FastAPI 中一样使用这些方法。
以下为一个完整的 CRUD 示例:

from nest.core import Controller, Get, Post, Put, Delete
from .book_service import BookService
from .book_models import Book@Controller('/books')
class BooksController:def __init__(self, book_service: BookService):self.book_service = book_service@Get('/')def get_books(self):return self.book_service.get_books()@Get('/:book_id')def get_book(self, book_id: int):return self.book_service.get_book(book_id)@Post('/')def add_book(self, book: Book):return self.book_service.add_book(book)@Put('/:book_id')def update_book(self, book_id: int , book: Book):return self.book_service.update_book(book_id, book)@Delete('/:book_id')def delete_book(self, book_id: int):return self.book_service.delete_book(book_id)

3、Providers

服务(Providers),是一个带有@Injectable装饰器注解的类,是 PyNest 应用程序的基础。它们处理业务逻辑和其他功能,充当可注入到其他组件(例如控制器)的依赖项。本指南通过各种示例讲解了什么是提供程序、如何使用它们、如何在模块中导入和导出它们,以及如何将它们注入到控制器和其他服务中。
定义Provider

from nest.core import Injectable@Injectable
class LoggerService:def log(self, message: str):print(f"LOG: {message}")

在例子中,LoggerService使用@Injectable装饰器将类定义为提供程序。现在可以将此类注入到同一模块内的其他类中,或将其导出以供其他模块使用。

在模块中注册Provider

from nest.core import Module
from .s3_service import S3Service
from src.providers.logger.logger_service import LoggerService
from src.providers.logger.logger_module import LoggerModule@Module(providers=[S3Service, LoggerService],exports=[S3Service],imports=[LoggerModule],
)
class S3Module:pass

在例子中:S3Module 定义了一个提供 S3Service 的模块,并将其导出以供其他模块使用。它还导入了 LoggerModule 以使用 LoggerService。

将Provider注入Controller

from nest.core import Controller, Post
from .s3_service import S3Service@Controller('/s3')
class S3Controller:def __init__(self, s3_service: S3Service):self.s3_service = s3_service@Post('/upload')def upload_file(self, file_name: str):self.s3_service.upload_file(file_name)return {"message": "File uploaded successfully!"}

在这个例子中,S3Service通过构造函数注入到了S3Controller中。

将Provider注入其他Provider

from nest.core import Injectable
from src.providers.logger.logger_service import LoggerService@Injectable
class S3Service:def __init__(self, logger_service: LoggerService):self.logger_service = logger_servicedef upload_file(self, file_name: str):print(f"Uploading {file_name}")self.logger_service.log(f"Uploaded file: {file_name}")

4、ORM Provider

pyNest内置了基于SQLAlchemy的数据库连接组件,它包括了OrmProvider( 同步)、AsyncOrmProvider( 异步)两个服务。
以下是AsyncOrmProvider的使用示例:
config.py

from nest.core.database.orm_provider import AsyncOrmProvider
import os
from dotenv import load_dotenvload_dotenv()config = AsyncOrmProvider(db_type="postgresql",config_params=dict(host=os.getenv("POSTGRESQL_HOST", "localhost"),db_name=os.getenv("POSTGRESQL_DB_NAME", "default_nest_db"),user=os.getenv("POSTGRESQL_USER", "postgres"),password=os.getenv("POSTGRESQL_PASSWORD", "postgres"),port=int(os.getenv("POSTGRESQL_PORT", 5432)),)
)

app_schema.py

from src.config import config
from sqlalchemy import Integer, String
from sqlalchemy.orm import Mapped, mapped_columnclass Example(config.Base):__tablename__ = "example"id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)name: Mapped[str] = mapped_column(String, unique=True)

app_service.py

from .examples_model import Examples
from .examples_entity import Examples as ExamplesEntity
from src.config import config
from nest.core.decorators.database import async_db_request_handler
from nest.core import Injectable
from sqlalchemy import select@Injectable
class ExamplesService:def __init__(self):self.orm_config = configself.session = self.orm_config.get_session@async_db_request_handlerasync def add_examples(self, examples: Examples):examples_entity = ExamplesEntity(**examples.dict())async with self.session() as session:session.add(examples_entity)await session.commit()return examples_entity.id@async_db_request_handlerasync def get_examples(self):query = select(ExamplesEntity)async with self.session() as session:result = await session.execute(query)return result.scalars().all()

app_controller.py

from nest.core import Controller, Get, Postfrom .examples_service import ExamplesService
from .examples_model import Examples@Controller("examples")
class ExamplesController:def __init__(self, service: ExamplesService):self.service = service@Get("/")async def get_examples(self):return await self.service.get_examples()@Post("/")async def add_examples(self, examples: Examples):return await self.service.add_examples(examples)

app_module.py

from .config import config
from .example.example_module import ExampleModulefrom .app_controller import AppController
from .app_service import AppServicefrom nest.core import Module, PyNestFactory@Module(imports=[ExampleModule],controllers=[AppController],providers=[AppService],
)
class AppModule:passapp = PyNestFactory.create(AppModule, description="This is my FastAPI app drive by Async ORM Engine", title="My App",version="1.0.0", debug=True)http_server = app.get_server()@http_server.on_event("startup")
async def startup():await config.create_all()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/77660.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML 详解:从基础结构到语义标签

目录 一、HTML 是什么&#xff1f;二、HTML 的基本结构✅ 简要说明&#xff1a; 三、常见 HTML 标签讲解3.1 标题标签 <h1> ~ <h6>3.2 段落和换行3.3 超链接3.4 图像插入3.5 列表无序列表&#xff1a;有序列表&#xff1a; 3.6 表格结构 四、HTML 语义化标签详解五…

用Python做有趣的AI项目 6:AI音乐生成器(LSTM Melody Generator)

&#x1f3b5; 项目名称&#xff1a;AI音乐生成器&#xff08;LSTM Melody Generator&#xff09; &#x1f9e0; 项目简介 这个项目的目标是&#xff1a;用 AI 来自动生成简单的旋律&#xff08;MIDI格式&#xff09;&#xff0c;类似于基础的钢琴曲、背景音乐片段。 我们使…

【运维】利用任务计划程序定时重启 nssm 服务 | Windows 服务每日定时维护实践

&#x1f680; 利用任务计划程序定时重启 nssm 服务 | Windows 服务每日定时维护实践 一、前言 在 Windows 系统中&#xff0c;nssm&#xff08;Non-Sucking Service Manager&#xff09; 是一个非常好用的工具&#xff0c;可以将任意可执行程序注册为系统服务。很多运维场景…

MATLAB小试牛刀系列(1)

问题描述 某机床厂生产甲、乙两种机床&#xff0c;每台机床销售后的利润分别为 4 千元与 3 千元。生产甲机床需用 A、B 机器加工&#xff0c;加工时间分别为每台 2h 和每台 1h&#xff1b;生产乙机床需用 A、B、C 三种机器加工&#xff0c;加工时间均为每台 1h。若每天可用于加…

云原生周刊:Kubernetes v1.33 正式发布

开源项目推荐 Robusta Robusta 是一个开源的 K8s 可观测性与自动化平台&#xff0c;旨在增强 Prometheus 告警的智能化处理能力。它通过规则和 AI 技术对告警进行丰富化处理&#xff0c;自动附加相关的 Pod 日志、图表和可能的修复建议&#xff0c;支持智能分组、自动修复和高…

React速通笔记

相关视频&#xff1a; 黑马程序员前端React18入门到实战视频教程&#xff0c;从reacthooks核心基础到企业级项目开发实战&#xff08;B站评论、极客园项目等&#xff09;及大厂面试全通关_哔哩哔哩_bilibili 一、React介绍 React由Meta公司开发&#xff0c;是一个用于 构建W…

人工智能与机器学习:Python从零实现K-Means 算法

&#x1f9e0; 向所有学习者致敬&#xff01; “学习不是装满一桶水&#xff0c;而是点燃一把火。” —— 叶芝 我的博客主页&#xff1a; https://lizheng.blog.csdn.net &#x1f310; 欢迎点击加入AI人工智能社区&#xff01; &#x1f680; 让我们一起努力&#xff0c;共创…

【神经网络与深度学习】训练集与验证集的功能解析与差异探究

引言 在深度学习模型的训练过程中&#xff0c;训练集和验证集是两个关键组成部分&#xff0c;它们在模型性能的提升和评估中扮演着不可替代的角色。通过分析这两者的区别和作用&#xff0c;可以帮助我们深入理解模型的学习过程和泛化能力&#xff0c;同时为防止过拟合及优化超…

Macos m系列芯片环境下python3安装mysqlclient系列问题

最近学习python3&#xff0c;在安装mysqlclient的时候遇到了一些问题&#xff0c;直接使用哦pip install mysqlclient 直接报错了&#xff0c;记录一下解决方案。 环境信息 设备&#xff1a;Macbook Pro m1 系统&#xff1a;macos Sequoia 15.3.2 最终成功的python版本&#xf…

微信小程序-van-uploader的preview-size

preview-size支持数组格式 修改前修改后1、升级微信小程序里面的van版本:2、 重新构建npm3、重启微信开发工具 修改前 引用van组件的上传文件&#xff0c;设置预览图尺寸&#xff0c;刚开始设置的是preview-size“140”&#xff0c;出来的效果就是一个正方形。 修改后 1、升级…

2. 第一个网页:前端基础入门

第一个网页&#xff1a;前端基础入门 一、网页文件基础认知 1. 文件扩展名 .htm 或 .html 均为网页文件后缀&#xff0c;二者功能完全一致扩展名隐藏方法 系统设置 → 文件夹选项 → 查看 → 取消勾选「隐藏已知文件类型的扩展名」 二、前端发展简史 1. 浏览器战争与标准混…

云原生--核心组件-容器篇-7-Docker私有镜像仓库--Harbor

1、Harbor的定义与核心作用 定义&#xff1a; Harbor是由VMware开源的企业级容器镜像仓库系统&#xff0c;后捐赠给 CNCF (Cloud Native Computing Foundation)。它基于Docker Registry扩展了企业级功能&#xff0c;用于存储、分发和管理容器镜像&#xff08;如Docker、OCI标准…

Java项目与技术栈场景题深度解析

Java项目与技术栈场景题深度解析 在互联网大厂Java求职者的面试中&#xff0c;经常会被问到关于Java项目或技术栈的场景题。本文通过一个故事场景来展示这些问题的实际解决方案。 第一轮提问 面试官&#xff1a;马架构&#xff0c;欢迎来到我们公司的面试现场。请问您对Java…

SpringMVC 静态资源处理 mvc:default-servlet-handler

我们先来看看效果,当我把这一行注释掉的时候&#xff1a; 我们来看看页面&#xff1a; 现在我把注释去掉&#xff1a; 、 可以看到的是&#xff0c;这个时候又可以访问了 那么我们就可以想&#xff0c;这个 <mvc:default-servlet-handler />它控制着我们页面的访问…

【leetcode】最长公共子路径问题

滚动hash 滚动哈希&#xff08;rolling hash&#xff09;也叫 Rabin-Karp 字符串哈希算法&#xff0c;它是将某个字符串看成某个进制下的整数&#xff0c;并将其对应的十进制整数作为hash值。 滚动hash算法的推导 假设有一个长度为n的数组a[0],a[1],a[2],…a[n-1]&#xff0…

【Linux网络】:套接字之UDP

一、UDP和TCP协议 TCP &#xff08;Transmission Control Protocol 传输控制协议&#xff09;的特点&#xff1a; 传输层协议有连接&#xff08;在正式通信前要先建立连接&#xff09;可靠传输&#xff08;在内部帮我们做可靠传输工作&#xff09;面向字节流 UDP &#xff08;U…

React19 useOptimistic 用法

用法 乐观更新 发起异步请求时&#xff0c;先假设请求会成功立即更新 UI 给用户反馈若请求最终失败&#xff0c;再将 UI 恢复到之前的状态 const [optimisticState, addOptimistic] useOptimistic(state, updateFn) 参数 state&#xff1a;实际值&#xff0c;可以是 useSta…

Deepseek-v3+cline+vscode java自动化编程

1、Deepseek DeepSeek 充值后&#xff0c;创建apikey 2、vscode Visual Studio Code - Code Editing. Redefined 3、下载插件cline 4、配置deepeseek-v3 的密钥到cline 5、不可用 在开始的几次调用能正常使用起来&#xff0c;用了几次后&#xff0c;不能使用了&#xff0c;请求…

数据分析案例:环境数据分析

目录 数据分析案例&#xff1a;环境数据分析1. 项目背景2. 数据加载与预处理2.1 数据说明2.2 读取与清洗 3. 探索性数据分析&#xff08;EDA&#xff09;3.1 时序趋势3.2 日内变化3.3 气象与污染物相关性 4. 特征工程4.1 时间特征4.2 滞后与滚动统计4.3 目标变量 5. 模型构建与…

网络原理 - 8

目录 补充 网络层 IP 协议 基本概念&#xff1a; 协议头格式 地址管理 如何解决 IP 地址不够用呢&#xff1f;&#xff1f;&#xff1f; 1. 动态分配 IP 地址&#xff1a; 2. NAT 机制&#xff08;网络地址映射&#xff09; 3. IPv6 网段划分 一些特殊的 IP 地址 …