关于FastAPI与Vue3的通信
学习一下前后端分离技术,前端采用三大框架之一的Vue.js
,后端则采用Python
的FastAPI
框架。
一、前端设计
1.建目录 mydemo
2.在mydemo目录下打开命令行,运行:npm init vue@latest
(这里如果cmd卡死了,就ctrl + C 结束,再次运行npm init vue@latest )
3.工程名设置为 frontend ,其余按默认
4.按提示依次运行:
cd frontend
npm install
npm run dev
5.此时在浏览器中输入网址:http://127.0.0.1:5173/ (或者:http://localhost:5173)
,即会看到页面
对于前端,我们主要编辑 mydemo\frontend\src 下的文件:
6.修改 App.vue 内容如下:
<script> export default { data() { return { msg: "你好,世界!", }; }, }; </script> <template> <button >第一个按钮</button> <p>{{ msg }}</p> </template>
只需要保存,页面立即改变(热更新)。
至此,我们完成了前端的示例。
二、后端设计
1.安装FastAPI
,在命令窗口运行:
pip install fastapi pip install "uvicorn[standard]"
接下来在mydemo
文件夹下创建一个backend
文件夹,用以存放后端文件:
cd mydemo
mkdir backend
2.在backend
文件夹中创建一个main.py
文件,其中代码如下:
from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"}
保存后,在backend
路径的命令窗口运行以下代码:
uvicorn main:app --reload --port 8001
在浏览器地址栏输入http://127.0.0.1:8001
即可看到后端服务器返回的页面
至此,后端服务器的最小例子也建立了。
三、前端获取后端的数据
这时需要用到两个包,即前端需要用到axios
这个包,后端则要用到CORS
这个中间件。
1.前端, 安装axios
,在frontend
文件夹的命令窗口下运行以下命令:
npm install axios
修改frontend/src/main.js
文件如下:
import './assets/main.css' import { createApp } from 'vue' import App from './App.vue' import axios from 'axios' axios.defaults.withCredentials = true; axios.defaults.baseURL = 'http://127.0.0.1:8001' createApp(App).mount('#app')
上面代码的目的是:导入axios
,并且告诉前端axios,后端地址是http://127.0.0.1:8001
2. 接着在frontend/src/App.vue
中,添加获取数据的代码如下:
<script> import axios from "axios"; export default { data() { return { msg: "你好,世界!", }; }, methods: { getMessage() { axios.get("/").then((res) => { this.msg = res.data; }); }, }, }; </script> <template> <button @click="getMessage">第一个按钮</button> <p>{{ msg }}</p> </template>
在上述代码中,给按钮绑定了一个click
事件,当这个按钮被点击时,它会调用getMessage()
函数,该函数中用axios
去获得后端根目录下的数据,然后将要显示的文字更改为相应的返回值{hello:world}
。
至此,前端配置完成,当然,此时点击页面按钮不会有任何反应,如果打开网页开发工具中的控制台,你会看到有关 跨域资源共享 (CORS) 的错误信息:
3. 后端的设置
在FastAPI
中,设置CORS
是很简单的,只不过要注意的是,当前端的axios.defaults.withCredentials
设置为true
时,后面的响应地址就必须明确为字符串,而不能是一个列表,这里的意思是,当跨域访问需要带session
时,只能响应确定的地址请求。
添加中间件CORS
的代码至后端的main.py, 如下:
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins= "http://127.0.0.1:5173/", allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/") def read_root(): return {"Hello": "World"}
至此,后端代码修改完毕。
此时,当点击一下页面的按钮,其下方的文字将变成后端FastAPI
发送的信息 (我这里还是不行,可能是在局域网中的原因,需要将上面代码中的http://127.0.0.1:5173 改为 http://localhost:5173/ 才行)
这就完成了从服务器端获取数据的过程。
四、前端向后端发送数据
1.客户端设置
先在frontend/src/App.vue
中添加一个发送的方法,同时添加一个按钮,当用户点击该按钮时,调用axios
发送数据给服务器端,修改代码如下:
<script> import axios from "axios"; export default { data() { return { msg: "你好,世界!", }; }, methods: { sendMessage () { axios.post( "/update_item/", {name: "张无忌", age:24}, ).then((res) => { console.log(res.data); }); }, getMessage() { axios.get("/").then((res) => { this.msg = res.data; }); }, }, }; </script> <template> <button @click="getMessage">第一个按钮</button> <button @click="sendMessage">发送信息给服务器</button> <p>{{ msg }}</p> </template>
这里要注意的是,axios
发送数据时,其数据是以字典
的形式发送,当然也可以看作是json
格式。
在这里,axios
提交的路径是/update_item/
,因此服务器端必须建立该路由。
2.服务器端设置
为了接受客户端提交过来的数据,要进行两步操作:一是设立相应的路由地址,二是设置接受数据的模型,此时用到pydantic
,该包会在安装fastAPI
时同步安装,该包的主要功能是对接口数据进行定义、检查与管理。
在下面示例中,我们定义一个Item
类来接受客户端提交的数据,backend/main.py
的代码修改如下:
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from typing import Union class Item(BaseModel): name: str age: float is_TrueMan: Union[bool, None]=None app = FastAPI() app.add_middleware( CORSMiddleware, allow_origins= "http://localhost:5173/", allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) @app.get("/") def read_root(): return {"Hello": "World"} @app.post("/update_item/") def update_item(item: Item): item.age += 10 print(item) return {'item':item}
这里将接受到的人员年龄增加10后,打印在服务器端的控制台上,并将修改的结果返回给客户端,由客户端打印在浏览器的控制台上
至此,我们完成了一个客户端与服务器端完整的通信程序。
下一篇,我们将vue3前端打包集成到后端fastAPI的uvicorn服务器,详见:
使用python库uvicorn替代Nginx发布Vue3项目 (https://www.cnblogs.com/pu369/p/17850570.html)
参考:https://zhuanlan.zhihu.com/p/632387477
https://www.jianshu.com/p/987383cf6929
https://blog.csdn.net/bosivip/article/details/128141950