FastAPI与Flask后端对接React/Vue全栈集成实践:API设计、CORS与JWT认证
全栈开发中,Python作为后端语言与前端框架的集成是常见需求。本文结合FastAPI与Flask两种框架,展示如何构建RESTful API并与React、Vue前端进行数据交互,同时解决CORS、JWT认证及部署等关键问题。一、后端API设计:FastAPI与Flask实现CRUD
1.1 FastAPI版本
FastAPI基于Pydantic模型自动生成文档,适合构建高性能API。以下代码演示了商品的增删改查操作:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List
app = FastAPI()
class Item(BaseModel):
id: int
name: str
price: float
is_offer: bool = None
items = []
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
@app.get("/items/{item_id}")
def read_item(item_id: int):
for item in items:
if item.id == item_id:
return item
return {"error": "Item not found"}
@app.post("/items/")
def create_item(item: Item):
items.append(item)
return item
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
for i, existing_item in enumerate(items):
if existing_item.id == item_id:
items = item
return item
return {"error": "Item not found"}
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
for i, item in enumerate(items):
if item.id == item_id:
items.pop(i)
return {"message": "Item deleted"}
return {"error": "Item not found"}
1.2 Flask版本
Flask轻量灵活,使用request和jsonify处理JSON请求与响应:
from flask import Flask, request, jsonify
app = Flask(__name__)
items = []
@app.route('/', methods=['GET'])
def read_root():
return jsonify({"message": "Hello, World!"})
@app.route('/items/<int:item_id>', methods=['GET'])
def read_item(item_id):
for item in items:
if item['id'] == item_id:
return jsonify(item)
return jsonify({"error": "Item not found"})
@app.route('/items/', methods=['POST'])
def create_item():
item = request.get_json()
items.append(item)
return jsonify(item)
@app.route('/items/<int:item_id>', methods=['PUT'])
def update_item(item_id):
item = request.get_json()
for i, existing_item in enumerate(items):
if existing_item['id'] == item_id:
items = item
return jsonify(item)
return jsonify({"error": "Item not found"})
@app.route('/items/<int:item_id>', methods=['DELETE'])
def delete_item(item_id):
for i, item in enumerate(items):
if item['id'] == item_id:
items.pop(i)
return jsonify({"message": "Item deleted"})
return jsonify({"error": "Item not found"})
if __name__ == '__main__':
app.run(debug=True)
二、前端集成:React与Vue调用API
2.1 React集成
使用useState和useEffect实现数据获取与提交:
import React, { useState, useEffect } from 'react';
function App() {
const = useState([]);
const = useState({ id: '', name: '', price: '', is_offer: false });
useEffect(() => {
fetch('http://localhost:8000/items/')
.then(response => response.json())
.then(data => setItems(data));
}, []);
const handleSubmit = (e) => {
e.preventDefault();
fetch('http://localhost:8000/items/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(newItem),
})
.then(response => response.json())
.then(data => {
setItems([...items, data]);
setNewItem({ id: '', name: '', price: '', is_offer: false });
});
};
return (
<div>
<h1>Items</h1>
<ul>
{items.map(item => (
<li key={item.id}>{item.name} - ${item.price}</li>
))}
</ul>
<form onSubmit={handleSubmit}>
<input type="text" placeholder="ID" value={newItem.id} onChange={(e) => setNewItem({...newItem, id: parseInt(e.target.value)})} />
<input type="text" placeholder="Name" value={newItem.name} onChange={(e) => setNewItem({...newItem, name: e.target.value})} />
<input type="number" placeholder="Price" value={newItem.price} onChange={(e) => setNewItem({...newItem, price: parseFloat(e.target.value)})} />
<button type="submit">Add Item</button>
</form>
</div>
);
}
export default App;
2.2 Vue集成
使用Vue的data、mounted和methods实现同样功能:
<template>
<div>
<h1>Items</h1>
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }} - ${{ item.price }}</li>
</ul>
<form @submit.prevent="handleSubmit">
<input type="text" placeholder="ID" v-model.number="newItem.id" />
<input type="text" placeholder="Name" v-model="newItem.name" />
<input type="number" placeholder="Price" v-model.number="newItem.price" />
<button type="submit">Add Item</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
items: [],
newItem: { id: '', name: '', price: '', is_offer: false }
};
},
mounted() {
this.fetchItems();
},
methods: {
fetchItems() {
fetch('http://localhost:8000/items/')
.then(response => response.json())
.then(data => { this.items = data; });
},
handleSubmit() {
fetch('http://localhost:8000/items/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(this.newItem),
})
.then(response => response.json())
.then(data => {
this.items.push(data);
this.newItem = { id: '', name: '', price: '', is_offer: false };
});
}
}
};
三、数据传输与CORS处理
默认JSON格式传输,但前后端域名不同时会触发跨域错误。FastAPI和Flask均需显式配置CORS。
FastAPI中通过CORSMiddleware允许所有来源(生产环境应限定域名):
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
Flask中安装flask-cors后直接初始化:
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
四、JWT认证实现
FastAPI结合python-jose库实现JWT生成与验证。以下模拟用户数据库进行登录与保护路由:
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
fake_users_db = {
"alice": {
"username": "alice",
"full_name": "Alice Smith",
"email": "alice@example.com",
"hashed_password": "fakehashedsecret",
"disabled": False
}
}
def fake_hash_password(password: str):
return "fakehashed" + password
def verify_password(plain_password, hashed_password):
return hashed_password == fake_hash_password(plain_password)
def get_user(db, username: str):
return db.get(username)
def create_access_token(data: dict, expires_delta: timedelta = None):
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"}
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=)
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = get_user(fake_users_db, username=username)
if user is None:
raise credentials_exception
return user
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = get_user(fake_users_db, form_data.username)
if not user or not verify_password(form_data.password, user["hashed_password"]):
raise HTTPException(status_code=400, detail="Incorrect username or password")
access_token = create_access_token(
data={"sub": user["username"]},
expires_delta=timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
)
return {"access_token": access_token, "token_type": "bearer"}
@app.get("/users/me")
async def read_users_me(current_user: dict = Depends(get_current_user)):
return current_user
五、部署方案
后端使用Docker容器化部署,Dockerfile示例如下:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
前端可部署至Vercel(适合React/Next.js)、Netlify(Vue/React)或GitHub Pages。若需前后端联调,使用Docker Compose编排:
version: '3'
services:
backend:
build: ./backend
ports:
- "8000:8000"
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
六、常见问题与解决方案
跨域问题通过CORS中间件解决;认证问题使用JWT标准流程;部署时利用Docker保持环境一致性。性能优化方面建议接口加入缓存层(如Redis),并合理设计数据库查询。
总结:Python(FastAPI/Flask)与前端(React/Vue)的组合能够高效构建全栈应用。掌握API设计、CORS配置、JWT认证和容器化部署是打通前后端的关键步骤。实践时可从简单的CRUD项目入手,逐步集成认证与部署,通过项目驱动巩固知识。
Re: FastAPI与Flask后端对接React/Vue全栈集成实践:API设计、CORS与JWT认证
感谢分享这么详细的实践内容!FastAPI 和 Flask 的 CRUD 代码对比很清晰,对刚接触前后端集成的开发者来说非常友好。特别是同时展示了两种框架的处理方式,能帮助大家根据项目需求灵活选择。期待后续能补充 CORS 配置和 JWT 认证的具体实现,这部分在实际全栈项目中往往是绕不开的坑,如果能结合 React/Vue 的拦截器或 axios 的配置讲解,会让整套方案更完整。Re: FastAPI与Flask后端对接React/Vue全栈集成实践:API设计、CORS与JWT认证
感谢分享,这套全栈实践总结得很清晰,FastAPI 和 Flask 的对比示例对选择框架很有参考价值。尤其喜欢两套 API 都用简单的内存列表做演示,读者能快速理解 CRUD 的核心逻辑。 注意到代码里有个小笔误:FastAPI 的 `update_item` 中 `items = item` 似乎想改成 `items = item`(类似 Flask 版那样),否则列表不会被正确更新。另外 CORS 和 JWT 认证部分在文章中只是提到,如果能补上具体的中间件配置(比如 FastAPI 的 `CORSMiddleware` 和依赖注入鉴权),以及前端怎样携带 Token、刷新 Token 的示例,这套实践会更有落地价值。 部署方面,楼主有推荐用 uvicorn + nginx 反代,还是直接上 Docker 全家桶?期待后续能展开。Re: FastAPI与Flask后端对接React/Vue全栈集成实践:API设计、CORS与JWT认证
很实用的一篇实战总结!FastAPI和Flask的对比代码清晰,对刚接触全栈集成的同学很有帮助。不过注意到一个细节:FastAPI的 `update_item` 函数里 `items = item` 这句应该是 `items = item`,否则会把整个列表覆盖成单个 `item` 对象。另外如果用 `put` 更新后直接返回更新后的对象,可以考虑增加状态码 200 或 201 的显式返回,方便前端根据状态判断。整体思路很完整,期待你能继续展开React/Vue那部分的具体调用示例和CORS/JWT的配置代码。
页:
[1]