Python全栈开发2026:FastAPI + Vue3 + Docker从零到部署完整指南
·
Python全栈开发2026:FastAPI + Vue3 + Docker从零到部署完整指南
引言
Python全栈开发依然是2026年最适合零基础入门的技术方向——语法简洁像"伪代码",生态完善能覆盖从后端到数据分析的全场景,就业面广(Web开发、自动化、AI应用等都能做),而且企业对Python全栈开发者的需求仍在持续增长。
本文将提供一份完整的2026年Python全栈开发路线,从基础语法到生产部署,全程可操作、可落地。核心技术栈为:FastAPI(后端)+ Vue 3(前端)+ Docker(部署),这也是当前企业中使用最广泛的Python全栈组合。
一、Python全栈学习路线总览
Python全栈开发的核心是"前端 + 后端 + 数据库 + 部署"的闭环能力。整个学习过程拆解为6个阶段:
| 阶段 | 内容 | 时间 | 目标 |
|---|---|---|---|
| 1 | Python基础语法 | 1-2周 | 掌握变量、函数、面向对象 |
| 2 | Web后端开发 | 3-4周 | 能用FastAPI写API |
| 3 | 前端基础与集成 | 2-3周 | Vue 3 + 前后端联调 |
| 4 | 数据库操作 | 2周 | SQLAlchemy + Redis |
| 5 | 项目实战 | 3-4周 | 完整项目从零到一 |
| 6 | 部署上线 | 1-2周 | Docker + Nginx + 云服务器 |
二、第一阶段:Python基础语法
这是所有学习的起点。核心知识点包括基础语法、面向对象、异常处理、模块化等。
# 基础函数与异常处理示例
def calculate_sum(num_list):
"""计算列表中数字的总和,包含异常处理"""
total = 0
try:
for num in num_list:
total += float(num)
except ValueError as e:
print(f"计算出错:输入包含非数字内容 - {e}")
return None
except Exception as e:
print(f"未知错误:{e}")
return None
return total
if __name__ == "__main__":
test_list = [1, 2, 3, 4.5]
print(f"列表 {test_list} 的和:{calculate_sum(test_list)}")
关键学习点
- 异步编程(asyncio):处理高并发的基础
- 类型系统:类型注解(Type Hints)在企业级代码维护中必不可少
- 现代工程化实践:使用虚拟环境、包管理、模块化设计
三、第二阶段:FastAPI后端开发
3.1 项目结构设计
一个好的项目结构是全栈开发的基础:
project/
├── backend/
│ ├── app/
│ │ ├── api/
│ │ │ ├── v1/
│ │ │ │ ├── endpoints/
│ │ │ │ │ ├── users.py
│ │ │ │ │ ├── products.py
│ │ │ │ │ └── orders.py
│ │ │ │ └── __init__.py
│ │ │ └── __init__.py
│ │ ├── core/
│ │ │ ├── config.py
│ │ │ ├── security.py
│ │ │ └── dependencies.py
│ │ ├── models/
│ │ │ ├── user.py
│ │ │ └── product.py
│ │ ├── schemas/
│ │ │ ├── user.py
│ │ │ └── product.py
│ │ ├── services/
│ │ │ ├── user_service.py
│ │ │ └── product_service.py
│ │ └── main.py
│ ├── alembic/
│ ├── tests/
│ ├── requirements.txt
│ └── Dockerfile
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ ├── views/
│ │ ├── stores/
│ │ ├── api/
│ │ └── router/
│ ├── package.json
│ └── Dockerfile
├── docker-compose.yml
└── README.md
3.2 核心配置与安全
# backend/app/core/config.py
from pydantic_settings import BaseSettings
from typing import Optional
from functools import lru_cache
class Settings(BaseSettings):
"""应用配置"""
# 应用
APP_NAME: str = "FullStack App"
DEBUG: bool = False
API_V1_PREFIX: str = "/api/v1"
# 数据库
DATABASE_URL: str = "postgresql+asyncpg://user:pass@localhost:5432/app"
# Redis
REDIS_URL: str = "redis://localhost:6379"
# JWT
SECRET_KEY: str = "change-me-in-production"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
REFRESH_TOKEN_EXPIRE_DAYS: int = 7
# CORS
CORS_ORIGINS: list[str] = ["http://localhost:5173"]
class Config:
env_file = ".env"
case_sensitive = True
@lru_cache()
def get_settings() -> Settings:
return Settings()
# backend/app/core/security.py
from datetime import datetime, timedelta
from jose import jwt
from passlib.context import CryptContext
from app.core.config import get_settings
settings = get_settings()
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)
def create_access_token(subject: str) -> str:
expire = datetime.utcnow() + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
return jwt.encode(
{"sub": subject, "exp": expire, "type": "access"},
settings.SECRET_KEY,
algorithm="HS256"
)
def create_refresh_token(subject: str) -> str:
expire = datetime.utcnow() + timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)
return jwt.encode(
{"sub": subject, "exp": expire, "type": "refresh"},
settings.SECRET_KEY,
algorithm="HS256"
)
3.3 RESTful API设计
# backend/app/api/v1/endpoints/products.py
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional
from app.core.dependencies import get_db, get_current_user
from app.schemas.product import ProductCreate, ProductResponse, ProductList
from app.services.product_service import ProductService
router = APIRouter(prefix="/products", tags=["products"])
@router.get("", response_model=ProductList)
async def list_products(
page: int = Query(1, ge=1),
page_size: int = Query(20, ge=1, le=100),
category: Optional[str] = None,
min_price: Optional[float] = None,
max_price: Optional[float] = None,
sort_by: Optional[str] = "created_at",
sort_order: Optional[str] = "desc",
db: AsyncSession = Depends(get_db),
):
"""商品列表查询,支持分页、筛选、排序"""
service = ProductService(db)
return await service.get_products(
page=page,
page_size=page_size,
category=category,
min_price=min_price,
max_price=max_price,
sort_by=sort_by,
sort_order=sort_order,
)
@router.get("/{product_id}", response_model=ProductResponse)
async def get_product(
product_id: int,
db: AsyncSession = Depends(get_db),
):
"""获取单个商品详情"""
service = ProductService(db)
product = await service.get_by_id(product_id)
if not product:
raise HTTPException(status_code=404, detail="商品不存在")
return product
@router.post("", response_model=ProductResponse, status_code=201)
async def create_product(
product_data: ProductCreate,
current_user = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""创建商品(需要登录)"""
service = ProductService(db)
return await service.create(product_data, current_user.id)
@router.put("/{product_id}", response_model=ProductResponse)
async def update_product(
product_id: int,
product_data: ProductCreate,
current_user = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""更新商品"""
service = ProductService(db)
product = await service.update(product_id, product_data, current_user.id)
if not product:
raise HTTPException(status_code=404, detail="商品不存在")
return product
@router.delete("/{product_id}", status_code=204)
async def delete_product(
product_id: int,
current_user = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
"""删除商品"""
service = ProductService(db)
success = await service.delete(product_id, current_user.id)
if not success:
raise HTTPException(status_code=404, detail="商品不存在")
四、第三阶段:Vue 3前端开发
4.1 项目初始化与配置
# 使用Vite创建Vue 3项目
npm create vite@latest frontend -- --template vue-ts
cd frontend
npm install
# 安装核心依赖
npm install vue-router@4 pinia axios
npm install -D @types/node tailwindcss @tailwindcss/vite
4.2 状态管理(Pinia)
// frontend/src/stores/auth.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { api } from '@/api/client'
import type { User, LoginRequest, RegisterRequest } from '@/types'
export const useAuthStore = defineStore('auth', () => {
const user = ref<User | null>(null)
const accessToken = ref<string | null>(localStorage.getItem('accessToken'))
const refreshToken = ref<string | null>(localStorage.getItem('refreshToken'))
const isAuthenticated = computed(() => !!accessToken.value)
async function login(credentials: LoginRequest) {
const response = await api.post('/auth/login', credentials)
accessToken.value = response.data.access_token
refreshToken.value = response.data.refresh_token
localStorage.setItem('accessToken', accessToken.value!)
localStorage.setItem('refreshToken', refreshToken.value!)
await fetchUser()
}
async function fetchUser() {
const response = await api.get('/users/me')
user.value = response.data
}
async function register(data: RegisterRequest) {
await api.post('/auth/register', data)
}
function logout() {
user.value = null
accessToken.value = null
refreshToken.value = null
localStorage.removeItem('accessToken')
localStorage.removeItem('refreshToken')
}
return {
user,
accessToken,
isAuthenticated,
login,
register,
logout,
fetchUser,
}
})
4.3 组合式API实战
<!-- frontend/src/views/Products.vue -->
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import { useProductStore } from '@/stores/products'
import ProductCard from '@/components/ProductCard.vue'
import ProductFilter from '@/components/ProductFilter.vue'
import Pagination from '@/components/Pagination.vue'
const store = useProductStore()
const filters = ref({
category: '',
minPrice: null as number | null,
maxPrice: null as number | null,
sortBy: 'created_at',
sortOrder: 'desc' as 'asc' | 'desc',
})
const currentPage = ref(1)
onMounted(() => {
fetchProducts()
})
watch(filters, () => {
currentPage.value = 1
fetchProducts()
}, { deep: true })
watch(currentPage, () => {
fetchProducts()
})
async function fetchProducts() {
await store.fetchProducts({
page: currentPage.value,
page_size: 20,
...filters.value,
})
}
</script>
<template>
<div class="container mx-auto px-4 py-8">
<h1 class="text-3xl font-bold mb-8">商品列表</h1>
<ProductFilter v-model="filters" />
<div v-if="store.loading" class="grid grid-cols-4 gap-6">
<div v-for="i in 8" :key="i" class="animate-pulse">
<div class="bg-gray-200 h-48 rounded-lg mb-4" />
<div class="bg-gray-200 h-4 rounded w-3/4 mb-2" />
<div class="bg-gray-200 h-4 rounded w-1/2" />
</div>
</div>
<div v-else class="grid grid-cols-4 gap-6">
<ProductCard
v-for="product in store.products"
:key="product.id"
:product="product"
/>
</div>
<Pagination
v-model="currentPage"
:total="store.total"
:page-size="20"
class="mt-8"
/>
</div>
</template>
五、第四阶段:数据库设计与操作
5.1 数据模型设计
# backend/app/models/product.py
from sqlalchemy import Column, Integer, String, Float, Text, Boolean, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from app.models.base import Base
class Product(Base):
__tablename__ = "products"
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(200), nullable=False, index=True)
description = Column(Text)
price = Column(Float, nullable=False)
original_price = Column(Float)
stock = Column(Integer, default=0)
category = Column(String(50), index=True)
image_url = Column(String(500))
is_active = Column(Boolean, default=True)
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
owner_id = Column(Integer, ForeignKey("users.id"))
owner = relationship("User", back_populates="products")
5.2 Service层设计
# backend/app/services/product_service.py
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func, and_
from app.models.product import Product
from app.schemas.product import ProductCreate
class ProductService:
def __init__(self, db: AsyncSession):
self.db = db
async def get_products(self, **filters):
query = select(Product).where(Product.is_active == True)
if filters.get('category'):
query = query.where(Product.category == filters['category'])
if filters.get('min_price') is not None:
query = query.where(Product.price >= filters['min_price'])
if filters.get('max_price') is not None:
query = query.where(Product.price <= filters['max_price'])
# 总数
count_query = select(func.count()).select_from(query.subquery())
total = await self.db.scalar(count_query)
# 排序
sort_col = getattr(Product, filters.get('sort_by', 'created_at'))
if filters.get('sort_order') == 'asc':
query = query.order_by(sort_col.asc())
else:
query = query.order_by(sort_col.desc())
# 分页
page = filters.get('page', 1)
page_size = filters.get('page_size', 20)
query = query.offset((page - 1) * page_size).limit(page_size)
result = await self.db.execute(query)
products = result.scalars().all()
return {
"items": products,
"total": total,
"page": page,
"page_size": page_size,
"total_pages": (total + page_size - 1) // page_size
}
六、第五阶段:Docker部署
6.1 Docker Compose编排
# docker-compose.yml
version: '3.8'
services:
backend:
build: ./backend
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql+asyncpg://app_user:app_pass@db:5432/app_db
- REDIS_URL=redis://redis:6379
- SECRET_KEY=${SECRET_KEY}
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
volumes:
- ./backend:/app
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
frontend:
build: ./frontend
ports:
- "5173:5173"
volumes:
- ./frontend:/app
- /app/node_modules
depends_on:
- backend
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app_user
POSTGRES_PASSWORD: app_pass
POSTGRES_DB: app_db
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app_user"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redisdata:/data
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- backend
- frontend
volumes:
pgdata:
redisdata:
6.2 Nginx反向代理
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream backend {
server backend:8000;
}
upstream frontend {
server frontend:5173;
}
server {
listen 80;
server_name example.com;
# API代理
location /api/ {
proxy_pass http://backend;
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;
}
# 前端静态资源
location / {
proxy_pass http://frontend;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
总结
2026年的Python全栈开发,FastAPI + Vue 3 + Docker已经成为最主流的技术组合。FastAPI提供高性能异步后端,Vue 3的Composition API提供灵活的前端开发体验,Docker确保从开发到生产的环境一致性。
掌握这套技术栈,你就能独立完成从需求分析、数据库设计、API开发、前端界面到生产部署的完整流程。全栈能力不仅能提升薪资30%-50%,还能让你在求职中拥有更多选择。
更多推荐
所有评论(0)