跳到主要内容Python 与前端集成构建全栈应用指南 | 极客日志Python大前端
Python 与前端集成构建全栈应用指南
Python 与前端集成涉及 API 设计、框架对接、数据传输及安全认证等关键环节。通过 FastAPI 或 Flask 构建 RESTful 接口,结合 React 或 Vue 实现交互,利用 JSON 进行数据交换并配置 CORS 解决跨域问题。JWT 保障用户安全,Docker 简化部署流程。掌握这些技术栈组合,可高效开发功能完整的全栈应用。
GRACE Grace11 浏览 Python 与前端集成:构建全栈应用
一、后端 API 设计
1.1 使用 FastAPI 创建 RESTful API
FastAPI 是一个现代化的 Python Web 框架,基于类型提示,非常适合构建高性能的 RESTful API:
from fastapi import FastAPI
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI()
class Item(BaseModel):
id: int
name: str
price: float
is_offer: Optional[bool] = None
items_db = []
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
@app.get("/items/{item_id}")
def read_item(item_id: int):
for item in items_db:
if item.id == item_id:
return item
return {"error": "Item not found"}
@app.post("/items/")
def create_item():
items_db.append(item)
item
():
i, existing_item (items_db):
existing_item. == item_id:
items_db[i] = item
item
{: }
():
i, item (items_db):
item. == item_id:
items_db.pop(i)
{: }
{: }
item: Item
return
@app.put("/items/{item_id}")
def
update_item
item_id: int, item: Item
for
in
enumerate
if
id
return
return
"error"
"Item not found"
@app.delete("/items/{item_id}")
def
delete_item
item_id: int
for
in
enumerate
if
id
return
"message"
"Item deleted"
return
"error"
"Item not found"
1.2 使用 Flask 创建 RESTful API
Flask 轻量且灵活,适合中小型项目或快速原型开发:
from flask import Flask, request, jsonify
app = Flask(__name__)
items_db = []
@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_db:
if item['id'] == item_id:
return jsonify(item)
return jsonify({"error": "Item not found"}), 404
@app.route('/items/', methods=['POST'])
def create_item():
item = request.get_json()
items_db.append(item)
return jsonify(item), 201
@app.route('/items/<int:item_id>', methods=['PUT'])
def update_item(item_id):
item = request.get_json()
for i, existing_item in enumerate(items_db):
if existing_item['id'] == item_id:
items_db[i] = item
return jsonify(item)
return jsonify({"error": "Item not found"}), 404
@app.route('/items/<int:item_id>', methods=['DELETE'])
def delete_item(item_id):
for i, item in enumerate(items_db):
if item['id'] == item_id:
items_db.pop(i)
return jsonify({"message": "Item deleted"})
return jsonify({"error": "Item not found"}), 404
if __name__ == '__main__':
app.run(debug=True)
二、前端框架集成
2.1 与 React 集成
React 组件化开发模式清晰,配合 Hooks 管理状态非常方便:
import React, { useState, useEffect } from 'react';
function App() {
const [items, setItems] = useState([]);
const [newItem, setNewItem] = 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>
);
}
export default App;
2.2 与 Vue 集成
<!-- App.vue -->
<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 };
});
}
}
};
</script>
三、数据传输与安全
3.1 JSON 数据格式
JSON 是前后端交互的标准。Pydantic 模型可自动验证后端返回的数据结构:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
id: int
name: str
price: float
@app.get("/item", response_model=Item)
def get_item():
return {"id": 1, "name": "Item 1", "price": 10.99}
3.2 处理 CORS
跨域资源共享(CORS)是前后端分离架构中的常见问题,需在后端显式配置:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
@app.route('/')
def read_root():
return jsonify({"message": "Hello, World!"})
四、认证与授权
4.1 JWT 认证
JSON Web Token(JWT)是无状态的认证方案,适合分布式系统:
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from datetime import datetime, timedelta
from pydantic import BaseModel
app = FastAPI()
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
fake_users_db = {
"alice": {
"username": "alice",
"full_name": "Alice Smith",
"email": "[email protected]",
"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):
if username in db:
return db[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})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
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=[ALGORITHM])
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:
raise HTTPException(status_code=400, detail="Incorrect username or password")
if not verify_password(form_data.password, user["hashed_password"]):
raise HTTPException(status_code=400, detail="Incorrect username or password")
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user["username"]},
expires_delta=access_token_expires
)
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
五、部署实践
5.1 部署后端
# 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"]
5.2 部署前端
现代前端构建产物为静态文件,可使用 Vercel、Netlify 或 GitHub Pages 托管。
5.3 完整编排
Docker Compose 可一键启动前后端服务:
version: '3'
services:
backend:
build: ./backend
ports:
- "8000:8000"
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
六、技术选型视角
- Python:生态丰富,开发效率高,适合快速迭代。
- Rust:内存安全,性能优异,但学习曲线较陡。
在实际项目中,可根据团队技能储备和业务需求权衡选择。若追求交付速度,Python 是首选;若对并发性能有极致要求,可考虑 Rust 替代部分计算密集型模块。
七、实战建议
- 循序渐进:先掌握后端 API 基础,再深入前端交互。
- 文档优先:官方文档通常是最准确的参考源。
- 容器化部署:利用 Docker 解决环境依赖问题。
- 关注安全:务必在生产环境配置 HTTPS 并限制 CORS 来源。
通过合理组合这些技术栈,可以高效构建出功能完善、易于维护的全栈应用。
</div>
相关免费在线工具
- curl 转代码
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
- Base64 字符串编码/解码
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
- Base64 文件转换器
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
- Markdown转HTML
将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
- HTML转Markdown
将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
- JSON 压缩
通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online