Django vs FastAPI:2026年选择哪个Python Web框架?
Python有两个主流的Web框架:Django(“电池齐全”的老牌框架)和FastAPI(现代的异步新秀)。本指南将帮助您做出正确选择。
快速对比
| 特性 | Django | FastAPI |
|---|---|---|
| 诞生年份 | 2005(成熟) | 2018(现代) |
| 哲学 | 电池齐全 | 极简、专注 |
| 异步支持 | 部分(Django 4+) | 原生、一等公民 |
| ORM | 内置(优秀) | 无(使用SQLAlchemy) |
| 管理后台 | 内置(出色) | 无 |
| 性能 | 良好 | 优秀(约快3倍) |
| 学习曲线 | 陡峭 | 平缓 |
| 最佳场景 | 全栈应用、CMS | API、微服务 |
| 自动API文档 | 无(需添加drf-spectacular) | 内置(Swagger + ReDoc) |

Django:全栈框架
pip install django djangorestframework
django-admin startproject myproject
python manage.py startapp users
# models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
bio = models.TextField(blank=True)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_at']
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
title = models.CharField(max_length=255)
content = models.TextField()
published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
# serializers.py (DRF)
from rest_framework import serializers
class PostSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.get_full_name', read_only=True)
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author_name', 'published', 'created_at']
read_only_fields = ['created_at']
# views.py (DRF ViewSets)
from rest_framework import viewsets, permissions, filters
from django_filters.rest_framework import DjangoFilterBackend
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.select_related('author').filter(published=True)
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['author', 'published']
search_fields = ['title', 'content']
ordering_fields = ['created_at', 'title']
def perform_create(self, serializer):
serializer.save(author=self.request.user)
# urls.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('posts', PostViewSet)
urlpatterns = router.urls
Django的杀手级特性
# Django Admin — 零代码管理界面
from django.contrib import admin
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'published', 'created_at']
list_filter = ['published', 'created_at']
search_fields = ['title', 'content']
list_editable = ['published']
prepopulated_fields = {'slug': ('title',)}
# 内联编辑关联模型
class CommentInline(admin.TabularInline):
model = Comment
extra = 0
inlines = [CommentInline]
# Django ORM — 强大的查询接口
# 无需编写SQL即可完成复杂查询
active_authors = User.objects.annotate(
post_count=Count('posts', filter=Q(posts__published=True))
).filter(post_count__gt=0).order_by('-post_count')[:10]
# 批量操作
Post.objects.filter(created_at__lt=cutoff_date).update(archived=True)
Post.objects.bulk_create([Post(title=t, author=user) for t in titles])
FastAPI:现代API框架
pip install fastapi uvicorn[standard] sqlalchemy alembic pydantic-settings
# main.py
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI(
title="My API",
version="1.0.0",
docs_url="/docs", # Swagger UI自动生成!
redoc_url="/redoc",
)
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_methods=["*"],
allow_headers=["*"],
)
# schemas.py (Pydantic模型)
from pydantic import BaseModel, EmailStr, field_validator
from datetime import datetime
from typing import Optional
class UserCreate(BaseModel):
name: str
email: EmailStr
password: str
@field_validator('password')
@classmethod
def password_strong_enough(cls, v):
if len(v) < 8:
raise ValueError('密码长度至少8个字符')
return v
class UserResponse(BaseModel):
id: int
name: str
email: str
created_at: datetime
model_config = {"from_attributes": True} # 允许ORM模型→模式转换
class PostCreate(BaseModel):
title: str
content: str
published: bool = False
class PostResponse(PostCreate):
id: int
author_id: int
created_at: datetime
model_config = {"from_attributes": True}
# routers/posts.py
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from typing import List
router = APIRouter(prefix="/posts", tags=["posts"])
@router.get("/", response_model=List[PostResponse])
async def list_posts(
page: int = Query(default=1, ge=1),
limit: int = Query(default=20, le=100),
search: str = Query(default=None),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user_optional),
):
query = select(Post).where(Post.published == True)
if search:
query = query.where(Post.title.ilike(f"%{search}%"))
query = query.offset((page - 1) * limit).limit(limit)
result = await db.execute(query)
return result.scalars().all()
@router.post("/", response_model=PostResponse, status_code=status.HTTP_201_CREATED)
async def create_post(
post_data: PostCreate,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user), # 需要认证
):
post = Post(**post_data.model_dump(), author_id=current_user.id)
db.add(post)
await db.commit()
await db.refresh(post)
return post
@router.delete("/{post_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_post(
post_id: int,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
post = await db.get(Post, post_id)
if not post:
raise HTTPException(status_code=404, detail="文章未找到")
if post.author_id != current_user.id:
raise HTTPException(status_code=403, detail="不是您的文章")
await db.delete(post)
await db.commit()

FastAPI的杀手级特性
# 自动API文档在/docs(无需编写代码!)
# Pydantic类型安全——自动验证
# 异步优先——处理数千个并发请求
# 依赖注入优雅
async def get_db():
async with AsyncSessionLocal() as session:
yield session
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: AsyncSession = Depends(get_db)
) -> User:
payload = verify_jwt(token)
user = await db.get(User, payload["sub"])
if not user:
raise HTTPException(status_code=401, detail="用户未找到")
return user
# 后台任务
from fastapi import BackgroundTasks
@router.post("/users/")
async def register_user(
user_data: UserCreate,
background_tasks: BackgroundTasks,
db: AsyncSession = Depends(get_db),
):
user = await create_user(db, user_data)
background_tasks.add_task(send_welcome_email, user.email, user.name)
return user # 立即返回,邮件在后台发送
何时选择哪个
选择Django当:
- 构建全栈Web应用,使用HTML模板
- 需要Django Admin进行内容管理
- 团队已经熟悉Django
- 快速原型开发,电池齐全
- 复杂的ORM查询和数据库迁移
- 电子商务或CMS应用

选择FastAPI当:
- 构建纯REST API或微服务
- 性能至关重要(FastAPI比Django快约3倍)
- 需要原生异步支持
- 构建实时功能,如WebSocket
- 团队偏好显式而非隐式
- 数据科学或ML模型服务API
混合方案
许多团队同时使用两者:
Django:
- 内容编辑者的管理界面
- 邮件发送、文件上传
- 复杂ORM操作
- 后台任务(Celery)
FastAPI:
- 供React/Vue/移动端使用的公共REST API
- 实时WebSocket端点
- 高吞吐量微服务
- ML模型推理端点
总结
- Django:全栈、固执己见,适合内容密集型应用和偏好约定优于配置的团队
- FastAPI:API专注、高性能,适合希望显式控制和异步优先设计的开发者
两者都很优秀。选择取决于您的用例,而非哪个“更好”。
→ 使用JSON to YAML Converter在JSON和YAML配置格式之间转换。