news 2026/8/1 14:29:20

Python 全栈开发 2026:FastAPI + Vue3 + Docker 从零到部署完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 全栈开发 2026:FastAPI + Vue3 + Docker 从零到部署完整指南

Python 全栈开发 2026:FastAPI + Vue3 + Docker 从零到部署完整指南

一、引言

2026年的Python全栈开发,核心技术栈已经明确:FastAPI(后端)+ Vue 3(前端)+ Docker(部署)。这套组合是企业中使用最广泛的Python全栈方案,兼顾了开发效率、运行性能和运维便利性。

本文将提供一份完整的从零到部署的全栈开发指南,包含项目结构、前后端联调、数据库设计和生产部署,全程可操作、可落地。

二、整体架构设计

2.1 技术栈选型

层级技术选型说明
前端框架Vue 3 + TypeScriptComposition API, 响应式系统
构建工具Vite极速开发体验
UI组件库Element Plus成熟的企业级组件库
状态管理PiniaVue 3 官方推荐
后端框架FastAPI 2.0原生异步、自动文档
ORMSQLAlchemy 2.0异步支持
数据库PostgreSQL最先进的开源关系型数据库
缓存Redis高性能缓存
容器化Docker + Docker Compose一键部署
反向代理Nginx静态文件 + API代理

2.2 项目结构

fullstack-app/ ├── backend/ │ ├── app/ │ │ ├── main.py │ │ ├── config.py │ │ ├── dependencies.py │ │ ├── models/ │ │ ├── schemas/ │ │ ├── services/ │ │ ├── repositories/ │ │ └── routers/ │ ├── alembic/ │ ├── tests/ │ ├── Dockerfile │ └── requirements.txt ├── frontend/ │ ├── src/ │ │ ├── components/ │ │ ├── views/ │ │ ├── stores/ │ │ ├── api/ │ │ ├── router/ │ │ └── App.vue │ ├── Dockerfile │ ├── vite.config.ts │ └── package.json ├── nginx/ │ └── nginx.conf ├── docker-compose.yml └── .env

三、后端开发

3.1 配置管理

# backend/app/config.pyfrompydantic_settingsimportBaseSettingsfromtypingimportListclassSettings(BaseSettings):PROJECT_NAME:str="Fullstack App"VERSION:str="1.0.0"ENVIRONMENT:str="development"DEBUG:bool=True# 数据库DATABASE_URL:str="postgresql+asyncpg://user:password@localhost:5432/app"REDIS_URL:str="redis://localhost:6379/0"# JWTJWT_SECRET_KEY:str="your-secret-key-change-in-production"JWT_ALGORITHM:str="HS256"JWT_EXPIRE_MINUTES:int=60# CORSCORS_ORIGINS:List[str]=["http://localhost:5173"]model_config={"env_file":".env"}settings=Settings()

3.2 产品管理 API

# backend/app/routers/products.pyfromfastapiimportAPIRouter,HTTPException,status,QueryfromtypingimportList,Optionalfromapp.dependenciesimportDBSession,CurrentUser,Paginationfromapp.schemas.productimportProductCreate,ProductResponse,ProductUpdatefromapp.services.product_serviceimportProductService router=APIRouter()@router.post("/",response_model=ProductResponse,status_code=status.HTTP_201_CREATED)asyncdefcreate_product(data:ProductCreate,db:DBSession,user:CurrentUser):service=ProductService(db)returnawaitservice.create(data,user["id"])@router.get("/",response_model=dict)asyncdeflist_products(db:DBSession,pagination:Pagination,search:Optional[str]=Query(None),category:Optional[str]=Query(None),min_price:Optional[float]=Query(None),max_price:Optional[float]=Query(None),sort_by:Optional[str]=Query("created_at"),sort_order:Optional[str]=Query("desc"),):service=ProductService(db)items,total=awaitservice.list_with_filters(offset=pagination["offset"],limit=pagination["page_size"],search=search,category=category,min_price=min_price,max_price=max_price,sort_by=sort_by,sort_order=sort_order,)return{"items":items,"total":total,"page":pagination["page"],"page_size":pagination["page_size"],"total_pages":(total+pagination["page_size"]-1)//pagination["page_size"],}@router.get("/{product_id}",response_model=ProductResponse)asyncdefget_product(product_id:str,db:DBSession):service=ProductService(db)product=awaitservice.get_by_id(product_id)ifnotproduct:raiseHTTPException(status_code=404,detail="产品不存在")returnproduct@router.put("/{product_id}",response_model=ProductResponse)asyncdefupdate_product(product_id:str,data:ProductUpdate,db:DBSession,user:CurrentUser):service=ProductService(db)product=awaitservice.update(product_id,data,user["id"])ifnotproduct:raiseHTTPException(status_code=404,detail="产品不存在")returnproduct@router.delete("/{product_id}",status_code=status.HTTP_204_NO_CONTENT)asyncdefdelete_product(product_id:str,db:DBSession,user:CurrentUser):ifuser["role"]!="admin":raiseHTTPException(status_code=403,detail="权限不足")service=ProductService(db)success=awaitservice.delete(product_id)ifnotsuccess:raiseHTTPException(status_code=404,detail="产品不存在")

四、前端开发

4.1 API 封装

// frontend/src/api/client.tsimportaxiosfrom'axios';import{useAuthStore}from'@/stores/auth';importrouterfrom'@/router';constapiClient=axios.create({baseURL:import.meta.env.VITE_API_BASE_URL||'/api',timeout:10000,headers:{'Content-Type':'application/json',},});// 请求拦截器apiClient.interceptors.request.use((config)=>{constauthStore=useAuthStore();if(authStore.token){config.headers.Authorization=`Bearer${authStore.token}`;}returnconfig;},(error)=>Promise.reject(error));// 响应拦截器apiClient.interceptors.response.use((response)=>response.data,(error)=>{if(error.response?.status===401){constauthStore=useAuthStore();authStore.logout();router.push('/login');}returnPromise.reject(error);});exportdefaultapiClient;

4.2 产品管理 API

// frontend/src/api/products.tsimportapiClientfrom'./client';exportinterfaceProduct{id:string;name:string;description:string;price:number;category:string;stock:number;image_url:string;created_at:string;updated_at:string;}exportinterfaceProductListParams{page?:number;page_size?:number;search?:string;category?:string;min_price?:number;max_price?:number;sort_by?:string;sort_order?:string;}exportinterfaceProductListResponse{items:Product[];total:number;page:number;page_size:number;total_pages:number;}exportconstproductApi={list(params:ProductListParams={}){returnapiClient.get('/v1/products/',{params})asPromise<ProductListResponse>;},get(id:string){returnapiClient.get(`/v1/products/${id}`)asPromise<Product>;},create(data:Omit<Product,'id'|'created_at'|'updated_at'>){returnapiClient.post('/v1/products/',data)asPromise<Product>;},update(id:string,data:Partial<Product>){returnapiClient.put(`/v1/products/${id}`,data)asPromise<Product>;},delete(id:string){returnapiClient.delete(`/v1/products/${id}`);},};

4.3 Pinia 状态管理

// frontend/src/stores/products.tsimport{defineStore}from'pinia';import{ref,computed}from'vue';import{productApi,Product,ProductListParams}from'@/api/products';exportconstuseProductStore=defineStore('products',()=>{constitems=ref<Product[]>([]);consttotal=ref(0);constloading=ref(false);consterror=ref<string|null>(null);constcurrentPage=ref(1);constpageSize=ref(10);constfilters=ref<ProductListParams>({});consttotalPages=computed(()=>Math.ceil(total.value/pageSize.value));asyncfunctionfetchProducts(params?:ProductListParams){loading.value=true;error.value=null;try{constmergedParams={page:currentPage.value,page_size:pageSize.value,...filters.value,...params,};constresponse=awaitproductApi.list(mergedParams);items.value=response.items;total.value=response.total;currentPage.value=response.page;if(params){filters.value={...filters.value,...params};}}catch(e:any){error.value=e.response?.data?.detail||'获取产品列表失败';}finally{loading.value=false;}}asyncfunctioncreateProduct(data:Omit<Product,'id'|'created_at'|'updated_at'>){constproduct=awaitproductApi.create(data);awaitfetchProducts();returnproduct;}asyncfunctionupdateProduct(id:string,data:Partial<Product>){constproduct=awaitproductApi.update(id,data);constindex=items.value.findIndex((item)=>item.id===id);if(index!==-1){items.value[index]=product;}returnproduct;}asyncfunctiondeleteProduct(id:string){awaitproductApi.delete(id);items.value=items.value.filter((item)=>item.id!==id);total.value--;}return{items,total,loading,error,currentPage,pageSize,filters,totalPages,fetchProducts,createProduct,updateProduct,deleteProduct,};});

4.4 Vue 3 组合式组件

<!-- frontend/src/views/ProductList.vue --> <script setup lang="ts"> import { onMounted, ref } from 'vue'; import { useProductStore } from '@/stores/products'; import { ElMessage, ElMessageBox } from 'element-plus'; import type { Product } from '@/api/products'; import ProductForm from '@/components/ProductForm.vue'; const store = useProductStore(); const showForm = ref(false); const editingProduct = ref<Product | null>(null); const searchQuery = ref(''); onMounted(() => { store.fetchProducts(); }); function handleSearch() { store.fetchProducts({ search: searchQuery.value || undefined }); } function handlePageChange(page: number) { store.currentPage = page; store.fetchProducts(); } function handleCreate() { editingProduct.value = null; showForm.value = true; } function handleEdit(product: Product) { editingProduct.value = { ...product }; showForm.value = true; } async function handleDelete(product: Product) { try { await ElMessageBox.confirm( `确定要删除产品「${product.name}」吗?`, '确认删除', { type: 'warning' } ); await store.deleteProduct(product.id); ElMessage.success('删除成功'); } catch { // 取消操作 } } async function handleFormSubmit(data: any) { try { if (editingProduct.value) { await store.updateProduct(editingProduct.value.id, data); ElMessage.success('更新成功'); } else { await store.createProduct(data); ElMessage.success('创建成功'); } showForm.value = false; } catch (e: any) { ElMessage.error(e.response?.data?.detail || '操作失败'); } } </script> <template> <div class="product-list"> <div class="toolbar"> <el-input v-model="searchQuery" placeholder="搜索产品..." @keyup.enter="handleSearch" style="width: 300px" > <template #append> <el-button @click="handleSearch">搜索</el-button> </template> </el-input> <el-button type="primary" @click="handleCreate">新增产品</el-button> </div> <el-table :data="store.items" v-loading="store.loading" stripe> <el-table-column prop="name" label="产品名称" /> <el-table-column prop="category" label="分类" width="120" /> <el-table-column prop="price" label="价格" width="120"> <template #default="{ row }"> ¥{{ row.price.toFixed(2) }} </template> </el-table-column> <el-table-column prop="stock" label="库存" width="100" /> <el-table-column label="操作" width="200"> <template #default="{ row }"> <el-button size="small" @click="handleEdit(row)">编辑</el-button> <el-button size="small" type="danger" @click="handleDelete(row)"> 删除 </el-button> </template> </el-table-column> </el-table> <el-pagination v-model:current-page="store.currentPage" :page-size="store.pageSize" :total="store.total" layout="total, prev, pager, next" @current-change="handlePageChange" /> <ProductForm v-if="showForm" :product="editingProduct" @submit="handleFormSubmit" @cancel="showForm = false" /> </div> </template>

五、Docker 部署

5.1 docker-compose.yml

version:'3.8'services:backend:build:./backendcontainer_name:fullstack-backendports:-"8000:8000"env_file:-.envdepends_on:postgres:condition:service_healthyredis:condition:service_startedrestart:unless-stoppednetworks:-app-networkfrontend:build:./frontendcontainer_name:fullstack-frontendports:-"3000:80"depends_on:-backendrestart:unless-stoppednetworks:-app-networkpostgres:image:postgres:16-alpinecontainer_name:fullstack-postgresenvironment:POSTGRES_USER:${POSTGRES_USER:-app}POSTGRES_PASSWORD:${POSTGRES_PASSWORD:-app_password}POSTGRES_DB:${POSTGRES_DB:-fullstack}volumes:-postgres_data:/var/lib/postgresql/datahealthcheck:test:["CMD-SHELL","pg_isready -U ${POSTGRES_USER:-app}"]interval:10stimeout:5sretries:5networks:-app-networkredis:image:redis:7-alpinecontainer_name:fullstack-redisvolumes:-redis_data:/datanetworks:-app-networknginx:image:nginx:alpinecontainer_name:fullstack-nginxports:-"80:80"volumes:-./nginx/nginx.conf:/etc/nginx/nginx.conf:rodepends_on:-backend-frontendrestart:unless-stoppednetworks:-app-networkvolumes:postgres_data:redis_data:networks:app-network:driver:bridge

5.2 Nginx 配置

events { worker_connections 1024; } http { upstream backend { server backend:8000; } upstream frontend { server frontend:80; } server { listen 80; # 前端静态资源 location / { proxy_pass http://frontend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # API 代理 location /api/ { proxy_pass http://backend/api/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } # WebSocket 支持 location /ws/ { proxy_pass http://backend/ws/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } } }

六、总结

FastAPI + Vue 3 + Docker的全栈技术栈组合,在2026年已经成为Python全栈开发的事实标准。这套组合的优势在于:

  1. FastAPI:原生异步、自动文档、类型安全,开发效率极高
  2. Vue 3:Composition API、响应式系统、Pinia状态管理,前端开发体验极佳
  3. Docker:一键部署、环境隔离、易于扩展,运维成本极低

完整的全栈开发流程:先设计数据模型→编写后端API→定义Pydantic Schema→开发前端页面→前后端联调→Docker部署。每一步都有清晰的最佳实践,开发者可以专注于业务逻辑而非基础设施。

对于想要快速交付全栈项目的团队来说,这套技术栈组合是2026年最高效的选择。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/1 14:28:28

Unity历史版本下载终极指南:告别官方链接失效烦恼

Unity历史版本下载终极指南&#xff1a;告别官方链接失效烦恼 【免费下载链接】download.unity.com Unity国际版下载&#xff0c;解决国内打不开网站和被重定向的问题 项目地址: https://gitcode.com/gh_mirrors/do/download.unity.com 还在为Unity官方下载链接失效而烦…

作者头像 李华
网站建设 2026/8/1 14:26:10

基于ESP32与MQTT的边缘AI图像识别结果实时上报方案

1. 项目概述&#xff1a;让边缘AI设备“开口说话”最近在折腾一个挺有意思的项目&#xff0c;用Seeed Studio的XIAO ESP32S3 Sense这块小板子做图像识别。板子本身集成了摄像头和麦克风&#xff0c;硬件上做边缘AI推理是绰绰有余的。我用的是SenseCraft AI这个平台&#xff0c;…

作者头像 李华
网站建设 2026/8/1 14:25:52

新手指南!入门级口粮红茶推荐:实测5款适配新手红茶

很多茶友入门时会混淆"英红"与"英德红茶"&#xff0c;其实二者有着明确区分&#xff1a;英德红茶是广东英德地区的红茶品类统称&#xff0c;而英红是独立品牌&#xff0c;是英德红茶的开创者与正统标杆&#xff0c;并非英德红茶的简称。作为始于1951年的老…

作者头像 李华
网站建设 2026/8/1 14:25:49

Jetson设备接入Allxon平台实现企业级OTA无线更新实战指南

1. 项目缘起&#xff1a;为什么嵌入式设备需要“无线更新”&#xff1f;在嵌入式开发和边缘计算领域&#xff0c;尤其是像 NVIDIA Jetson 系列这样的 AI 计算平台上&#xff0c;固件和应用程序的更新一直是个麻烦事。想象一下&#xff0c;你部署了成百上千台搭载 Jetson Orin N…

作者头像 李华
网站建设 2026/8/1 14:25:46

ncmdumpGUI:Windows平台下快速批量转换网易云音乐ncm文件的完整指南

ncmdumpGUI&#xff1a;Windows平台下快速批量转换网易云音乐ncm文件的完整指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾经在网易云音乐下载了…

作者头像 李华
网站建设 2026/8/1 14:23:37

《说文解字》入门指南:掌握汉字六书理论与文化密码

汉字密码解读&#xff1a;从《说文解字》入门到汉字本源探索 汉字作为世界上最古老的文字体系之一&#xff0c;承载着中华文明五千年的历史记忆。每个汉字都是一部浓缩的历史&#xff0c;而许慎的《说文解字》正是打开这部历史大门的钥匙。本文将带你系统掌握《说文解字》的阅读…

作者头像 李华