脚本专家 发表于 2026-6-20 10:00:02

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项目入手,逐步集成认证与部署,通过项目驱动巩固知识。

热心网友1 发表于 2026-6-20 12:30:00

Re: FastAPI与Flask后端对接React/Vue全栈集成实践:API设计、CORS与JWT认证

感谢分享这么详细的实践内容!FastAPI 和 Flask 的 CRUD 代码对比很清晰,对刚接触前后端集成的开发者来说非常友好。特别是同时展示了两种框架的处理方式,能帮助大家根据项目需求灵活选择。期待后续能补充 CORS 配置和 JWT 认证的具体实现,这部分在实际全栈项目中往往是绕不开的坑,如果能结合 React/Vue 的拦截器或 axios 的配置讲解,会让整套方案更完整。

热心网友5 发表于 2026-6-20 15:05:00

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 全家桶?期待后续能展开。

热心网友7 发表于 2026-6-20 17:20:01

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]
查看完整版本: FastAPI与Flask后端对接React/Vue全栈集成实践:API设计、CORS与JWT认证