1. Django框架概述:Python Web开发的瑞士军刀
Django作为Python生态中最成熟的Web框架之一,已经陪伴开发者走过了17个年头。我第一次接触Django是在2012年开发一个新闻聚合平台时,当时就被它"开箱即用"的特性所震撼。与其他框架不同,Django更像是一个完整的解决方案而非简单的工具集合。
1.1 框架设计哲学
Django遵循"包含电池"(Batteries-included)理念,这意味着一套标准的Django安装包已经包含了Web开发所需的大部分组件:
- ORM系统:用Python类定义数据模型,自动生成数据库表
- 模板引擎:分离业务逻辑与展示层
- 表单处理:内置CSRF防护、数据验证
- Admin后台:自动生成数据管理界面
- 认证系统:用户、权限、会话管理
- 缓存机制:支持Memcached、Redis等后端
- 国际化支持:多语言内容处理
这种设计显著降低了开发者的决策疲劳。我记得在早期使用Flask项目时,光是选择ORM就要比较SQLAlchemy、Peewee等五六个方案,而Django直接提供了经过实战检验的解决方案。
1.2 MTV架构解析
Django采用MTV模式(Model-Template-View),这与传统的MVC略有不同:
| 组件 | 职责 | 对应文件 | 类比说明 |
|---|---|---|---|
| Model | 数据存取逻辑 | models.py | 相当于建筑中的承重墙和地基 |
| Template | 展示层逻辑 | templates/*.html | 相当于室内装修和外观设计 |
| View | 业务逻辑处理 | views.py | 相当于房屋的功能分区规划 |
这种分离带来的最大好处是代码的可维护性。我曾接手过一个3万行代码的PHP项目,所有逻辑混在一起,而Django的强制分离让新开发者能快速定位问题所在。
2. 核心组件深度剖析
2.1 模型层:数据结构的艺术
Django的ORM是其最强大的武器之一。下面这个图书模型的例子展示了几个关键特性:
python复制from django.db import models
from django.core.validators import MinLengthValidator
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
bio = models.TextField(blank=True)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(
max_length=200,
validators=[MinLengthValidator(5)]
)
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name='books'
)
isbn = models.CharField(max_length=13, unique=True)
published_date = models.DateField()
price = models.DecimalField(max_digits=6, decimal_places=2)
class Meta:
ordering = ['-published_date']
indexes = [
models.Index(fields=['title']),
models.Index(fields=['author', 'published_date']),
]
def get_absolute_url(self):
return reverse('book-detail', args=[str(self.id)])
关键实践建议:
- 始终定义
__str__方法,这在调试和Admin界面中非常有用 - 使用
related_name明确反向查询名称,避免默认的_set语法 - 在Meta类中添加索引时要考虑查询模式,避免过度索引
- 为常用模型实现
get_absolute_url,方便在模板中使用
2.2 视图层:业务逻辑的中枢
Django支持函数视图和类视图两种风格。对于复杂视图,我强烈推荐使用基于类的视图(CBV):
python复制from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q
class BookSearchView(LoginRequiredMixin, ListView):
model = Book
template_name = 'books/search_results.html'
paginate_by = 20
context_object_name = 'book_list'
def get_queryset(self):
query = self.request.GET.get('q')
if query:
return Book.objects.filter(
Q(title__icontains=query) |
Q(author__name__icontains=query)
).select_related('author')
return Book.objects.none()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['search_query'] = self.request.GET.get('q', '')
return context
性能优化技巧:
- 使用
select_related和prefetch_related减少数据库查询次数 - 对于复杂查询条件,使用Q对象构建OR条件
- 分页处理一定要做,避免一次性加载大量数据
- 通过
get_context_data添加额外上下文而非直接修改self.object_list
2.3 模板系统:展示层的智慧
Django模板语言(DTL)刻意保持了简单性,这是为了避免在模板中编写复杂逻辑。一个良好的模板结构应该是这样的:
code复制templates/
├── base.html # 基础模板
├── includes/ # 可重用片段
│ ├── _header.html
│ └── _footer.html
└── books/
├── list.html # 书籍列表
└── detail.html # 书籍详情
示例模板代码:
html复制{% extends "base.html" %}
{% load static humanize %}
{% block title %}书籍搜索 - {{ search_query }}{% endblock %}
{% block content %}
<div class="container mt-4">
<form method="get" class="mb-4">
<div class="input-group">
<input type="text" name="q" value="{{ search_query }}"
class="form-control" placeholder="搜索书籍或作者">
<button type="submit" class="btn btn-primary">搜索</button>
</div>
</form>
{% if book_list %}
<div class="row">
{% for book in book_list %}
<div class="col-md-4 mb-4">
<div class="card h-100">
<div class="card-body">
<h5 class="card-title">{{ book.title }}</h5>
<p class="card-text text-muted">
作者: {{ book.author.name }}<br>
出版日期: {{ book.published_date|date:"Y年m月d日" }}<br>
价格: ¥{{ book.price|intcomma }}
</p>
</div>
<div class="card-footer bg-transparent">
<a href="{{ book.get_absolute_url }}" class="btn btn-sm btn-outline-primary">
查看详情
</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% include "includes/pagination.html" %}
{% else %}
<div class="alert alert-info">
{% if search_query %}
没有找到匹配的书籍
{% else %}
请输入搜索关键词
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}
模板最佳实践:
- 使用
{% extends %}实现模板继承,避免重复代码 - 将重复的UI元素拆分为
includes片段 - 善用模板过滤器格式化数据(如
|date,|intcomma) - 避免在模板中进行复杂计算,这些应该放在视图或模型方法中
- 为静态文件使用
{% static %}模板标签
3. Django高级实战技巧
3.1 项目结构优化
经过多个Django项目实践,我总结出以下推荐的项目结构:
code复制project_root/
├── config/ # 项目配置
│ ├── settings/ # 多环境配置
│ │ ├── base.py # 基础配置
│ │ ├── dev.py # 开发环境
│ │ └── prod.py # 生产环境
│ ├── urls.py # 主路由
│ └── wsgi.py
├── apps/ # 自定义应用
│ ├── users/ # 用户系统
│ ├── products/ # 产品模块
│ └── orders/ # 订单系统
├── static/ # 全局静态文件
│ ├── css/
│ ├── js/
│ └── images/
├── templates/ # 全局模板
│ ├── base.html
│ └── includes/
├── requirements/ # 依赖管理
│ ├── base.txt
│ ├── dev.txt
│ └── prod.txt
└── manage.py
关键决策点:
- 将settings拆分为多环境配置,通过环境变量
DJANGO_SETTINGS_MODULE切换 - 使用
apps/目录集中管理所有应用,保持项目整洁 - 分离不同环境的依赖,生产环境只安装必要包
- 全局模板和静态文件放在项目根目录,便于统一管理
3.2 数据库优化全攻略
Django ORM虽然方便,但不当使用会导致严重性能问题。以下是我总结的优化策略:
1. 查询优化
python复制# 反例:N+1查询问题
books = Book.objects.all()
for book in books:
print(book.author.name) # 每次循环都查询author表
# 正例:使用select_related
books = Book.objects.select_related('author').all()
for book in books:
print(book.author.name) # 仅1次查询
# 多对多关系使用prefetch_related
authors = Author.objects.prefetch_related('books').all()
for author in authors:
print([book.title for book in author.books.all()])
2. 批量操作
python复制# 反例:逐个创建
for i in range(100):
Book.objects.create(title=f'Book {i}')
# 正例:批量创建
Book.objects.bulk_create([
Book(title=f'Book {i}') for i in range(100)
])
# 批量更新
Book.objects.filter(
published_date__year=2020
).update(price=models.F('price') * 0.9)
3. 索引优化
python复制class Book(models.Model):
# 字段定义...
class Meta:
indexes = [
# 单字段索引
models.Index(fields=['title']),
# 复合索引
models.Index(fields=['author', 'published_date']),
# 条件索引
models.Index(
fields=['price'],
condition=models.Q(price__gte=100),
name='high_price_idx'
),
]
4. 高级技巧
python复制# 使用annotate进行聚合计算
from django.db.models import Count, Avg
authors = Author.objects.annotate(
book_count=Count('books'),
avg_price=Avg('books__price')
).filter(book_count__gt=5)
# 使用F表达式避免竞态条件
from django.db.models import F
Book.objects.filter(stock__gt=0).update(
stock=F('stock') - 1
)
# 使用Subquery进行复杂查询
from django.db.models import Subquery, OuterRef
newest_books = Book.objects.filter(
author=OuterRef('pk')
).order_by('-published_date')[:3]
authors = Author.objects.annotate(
newest_book_titles=Subquery(
newest_books.values('title')
)
)
3.3 安全防护体系
Django虽然内置了许多安全特性,但仍需正确配置:
1. 基础安全配置
python复制# settings/prod.py
SECURE_SSL_REDIRECT = True # 强制HTTPS
SESSION_COOKIE_SECURE = True # 仅HTTPS传输cookie
CSRF_COOKIE_SECURE = True # 仅HTTPS传输CSRF token
SECURE_BROWSER_XSS_FILTER = True # 启用XSS过滤器
SECURE_CONTENT_TYPE_NOSNIFF = True # 禁止MIME嗅探
X_FRAME_OPTIONS = 'DENY' # 防止点击劫持
2. 用户认证防护
python复制# 密码策略
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': {'min_length': 10}},
{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
]
# 登录限制
from django.contrib.auth import get_user_model
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
@receiver(user_logged_in)
def record_login(sender, request, user, **kwargs):
user.last_login_ip = request.META.get('REMOTE_ADDR')
user.save(update_fields=['last_login_ip'])
3. 数据验证
python复制from django import forms
from django.core.exceptions import ValidationError
from django.utils import timezone
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'published_date', 'price']
widgets = {
'published_date': forms.DateInput(attrs={'type': 'date'}),
}
def clean_published_date(self):
date = self.cleaned_data['published_date']
if date > timezone.now().date():
raise ValidationError("出版日期不能晚于今天")
return date
def clean(self):
cleaned_data = super().clean()
if cleaned_data.get('price', 0) < 0:
raise ValidationError("价格不能为负数")
return cleaned_data
4. 生产环境部署指南
4.1 现代化部署架构
典型的Django生产环境架构如下:
code复制用户 → CDN → 负载均衡器 → [Web服务器集群] → [应用服务器集群] → 数据库集群
↑ ↑
缓存集群 Celery workers
组件选择建议:
- Web服务器:Nginx (处理静态文件+反向代理)
- 应用服务器:Gunicorn或uWSGI
- 数据库:PostgreSQL (推荐) 或 MySQL
- 缓存:Redis (同时可用于Celery broker)
- 监控:Prometheus + Grafana
- 日志:ELK Stack (Elasticsearch, Logstash, Kibana)
4.2 详细部署步骤
1. 服务器准备
bash复制# 安装基础依赖
sudo apt update
sudo apt install -y python3-pip python3-dev libpq-dev nginx
# 创建系统用户
sudo useradd --system --group django
sudo mkdir -p /var/www/myproject
sudo chown django:django /var/www/myproject
2. 虚拟环境配置
bash复制python3 -m venv /var/www/myproject/venv
source /var/www/myproject/venv/bin/activate
pip install --upgrade pip
pip install gunicorn psycopg2-binary
pip install -r requirements.txt
3. Gunicorn配置
python复制# /var/www/myproject/gunicorn.conf.py
bind = 'unix:/var/www/myproject/myproject.sock'
workers = 3
worker_class = 'gthread'
threads = 3
max_requests = 1000
max_requests_jitter = 50
timeout = 30
keepalive = 5
user = 'django'
group = 'django'
errorlog = '/var/log/gunicorn.error.log'
accesslog = '/var/log/gunicorn.access.log'
capture_output = True
4. Systemd服务配置
ini复制# /etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=django
Group=django
WorkingDirectory=/var/www/myproject
ExecStart=/var/www/myproject/venv/bin/gunicorn \
--config /var/www/myproject/gunicorn.conf.py \
config.wsgi:application
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
5. Nginx配置
nginx复制# /etc/nginx/sites-available/myproject
upstream django_server {
server unix:/var/www/myproject/myproject.sock fail_timeout=0;
}
server {
listen 80;
server_name example.com;
client_max_body_size 20M;
location /static/ {
alias /var/www/myproject/static/;
expires 30d;
}
location /media/ {
alias /var/www/myproject/media/;
expires 30d;
}
location / {
proxy_set_header Host $http_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;
proxy_redirect off;
proxy_buffering off;
proxy_pass http://django_server;
}
}
4.3 性能调优参数
数据库连接池配置
python复制# settings/prod.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'db-server',
'PORT': '5432',
'CONN_MAX_AGE': 300, # 连接池保持时间(秒)
'OPTIONS': {
'connect_timeout': 5,
'application_name': 'myproject',
}
}
}
缓存配置
python复制CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://redis-server:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"PICKLE_VERSION": -1,
"SOCKET_CONNECT_TIMEOUT": 5,
"SOCKET_TIMEOUT": 5,
"IGNORE_EXCEPTIONS": True,
"CONNECTION_POOL_KWARGS": {
"max_connections": 100,
}
},
"KEY_PREFIX": "myproject"
}
}
# Session缓存
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
5. 常见问题与解决方案
5.1 部署问题排查
问题1:静态文件404错误
解决方案:
- 检查
STATIC_ROOT设置是否正确 - 确认Nginx配置中的
location /static/路径匹配 - 确保运行了
collectstatic命令 - 检查文件权限:
sudo chown -R django:django /var/www/myproject/static
问题2:数据库连接超时
解决方案:
- 增加
CONN_MAX_AGE减少连接创建开销 - 检查数据库服务器负载
- 配置连接池:
python复制DATABASES['default']['OPTIONS'] = { 'max_connections': 100, 'timeout': 30, }
5.2 开发中的常见陷阱
陷阱1:同步阻塞操作
错误示例:
python复制def some_view(request):
import requests
response = requests.get('https://api.example.com/data') # 同步请求阻塞事件循环
return JsonResponse(response.json())
解决方案:
python复制from django.http import JsonResponse
from django.views import View
import httpx
import asyncio
class AsyncApiView(View):
async def get(self, request):
async with httpx.AsyncClient() as client:
response = await client.get('https://api.example.com/data')
return JsonResponse(response.json())
陷阱2:未优化的Admin界面
优化建议:
python复制@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date', 'price')
list_select_related = ('author',) # 优化查询
list_filter = ('published_date', 'author')
search_fields = ('title', 'author__name')
date_hierarchy = 'published_date'
readonly_fields = ('created_at', 'updated_at')
def get_queryset(self, request):
return super().get_queryset(request).select_related('author')
5.3 性能瓶颈识别
诊断工具:
-
Django Debug Toolbar
python复制# settings/dev.py INSTALLED_APPS += ['debug_toolbar'] MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware'] INTERNAL_IPS = ['127.0.0.1'] -
Django Silk (性能分析)
python复制# settings/dev.py INSTALLED_APPS += ['silk'] MIDDLEWARE += ['silk.middleware.SilkyMiddleware'] SILKY_PYTHON_PROFILER = True -
数据库查询分析
python复制from django.db import connection def some_view(request): # 你的视图逻辑 print(connection.queries) # 打印所有SQL查询 return render(...)
优化案例:
原始代码:
python复制# 产生N+1查询
books = Book.objects.all()
for book in books:
print(book.author.name)
优化后:
python复制# 使用select_related
books = Book.objects.select_related('author').all()
for book in books:
print(book.author.name)
# 或者使用values/values_list避免加载整个模型
author_names = Book.objects.values_list('author__name', flat=True)
print(list(author_names))
6. 扩展Django生态系统
6.1 必备第三方包
| 类别 | 推荐包 | 用途 |
|---|---|---|
| API开发 | django-rest-framework | 构建RESTful API |
| 异步任务 | Celery | 后台任务处理 |
| 数据库 | django-environ | 环境变量管理 |
| 安全 | django-cors-headers | 跨域资源共享 |
| 表单 | django-crispy-forms | 美化表单渲染 |
| 测试 | pytest-django | 测试框架集成 |
| 部署 | whitenoise | 静态文件服务 |
| 监控 | django-prometheus | 监控指标暴露 |
6.2 自定义扩展技巧
创建自定义模板标签
python复制# books/templatetags/book_tags.py
from django import template
from django.utils.safestring import mark_safe
import markdown
register = template.Library()
@register.filter(name='markdown')
def markdown_format(text):
return mark_safe(markdown.markdown(text))
@register.simple_tag
def current_time(format_string):
from datetime import datetime
return datetime.now().strftime(format_string)
编写自定义中间件
python复制# config/middleware.py
import time
from django.utils.deprecation import MiddlewareMixin
class TimingMiddleware(MiddlewareMixin):
def process_request(self, request):
request.start_time = time.time()
def process_response(self, request, response):
duration = time.time() - request.start_time
response['X-Response-Time'] = f"{duration:.2f}s"
return response
创建管理命令
python复制# books/management/commands/export_books.py
from django.core.management.base import BaseCommand
from books.models import Book
import csv
class Command(BaseCommand):
help = 'Export books to CSV'
def add_arguments(self, parser):
parser.add_argument('file_path', type=str)
def handle(self, *args, **options):
with open(options['file_path'], 'w') as f:
writer = csv.writer(f)
writer.writerow(['Title', 'Author', 'Price'])
for book in Book.objects.all().select_related('author'):
writer.writerow([
book.title,
book.author.name,
book.price
])
self.stdout.write(
self.style.SUCCESS(f'Successfully exported to {options["file_path"]}')
)
7. 现代化Django开发实践
7.1 前后端分离架构
方案1:Django REST Framework (DRF)
python复制# books/api/serializers.py
from rest_framework import serializers
from books.models import Book
class BookSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.name', read_only=True)
class Meta:
model = Book
fields = ['id', 'title', 'author', 'author_name', 'price']
extra_kwargs = {
'author': {'write_only': True}
}
# books/api/views.py
from rest_framework import viewsets
from books.models import Book
from books.api.serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.select_related('author').all()
serializer_class = BookSerializer
def get_queryset(self):
queryset = super().get_queryset()
if search := self.request.query_params.get('search'):
queryset = queryset.filter(
Q(title__icontains=search) |
Q(author__name__icontains=search)
)
return queryset
方案2:GraphQL (使用Graphene)
python复制# books/schema.py
import graphene
from graphene_django import DjangoObjectType
from books.models import Book
class BookType(DjangoObjectType):
class Meta:
model = Book
fields = ('id', 'title', 'author', 'price')
class Query(graphene.ObjectType):
books = graphene.List(BookType, search=graphene.String())
def resolve_books(self, info, search=None, **kwargs):
queryset = Book.objects.select_related('author').all()
if search:
queryset = queryset.filter(
Q(title__icontains=search) |
Q(author__name__icontains=search)
)
return queryset
schema = graphene.Schema(query=Query)
7.2 微服务集成模式
服务间通信方案
-
同步HTTP调用
python复制import httpx def get_user_data(user_id): try: response = httpx.get( f'http://user-service/api/users/{user_id}', timeout=3.0 ) response.raise_for_status() return response.json() except httpx.RequestError as e: logger.error(f"User service request failed: {e}") return None -
异步消息队列(Celery + RabbitMQ)
python复制# tasks.py from celery import shared_task @shared_task(bind=True, max_retries=3) def process_order(self, order_id): try: order = Order.objects.get(id=order_id) # 处理订单逻辑... except Exception as exc: self.retry(exc=exc, countdown=60) -
gRPC集成
python复制# protobuf定义 syntax = "proto3"; service UserService { rpc GetUser (UserRequest) returns (UserResponse); } message UserRequest { int32 user_id = 1; } message UserResponse { int32 id = 1; string name = 2; string email = 3; } # Django端实现 import grpc from concurrent import futures from django.core.management.base import BaseCommand class UserService(user_pb2_grpc.UserServiceServicer): def GetUser(self, request, context): try: user = User.objects.get(id=request.user_id) return user_pb2.UserResponse( id=user.id, name=user.name, email=user.email ) except User.DoesNotExist: context.abort(grpc.StatusCode.NOT_FOUND, "User not found") class Command(BaseCommand): def handle(self, *args, **options): server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) user_pb2_grpc.add_UserServiceServicer_to_server( UserService(), server) server.add_insecure_port('[::]:50051') server.start() server.wait_for_termination()
7.3 测试策略与自动化
测试金字塔实践
-
单元测试
python复制from django.test import TestCase from books.models import Book class BookModelTest(TestCase): @classmethod def setUpTestData(cls): cls.author = Author.objects.create(name="Test Author") def test_book_creation(self): book = Book.objects.create( title="Test Book", author=self.author, price=29.99 ) self.assertEqual(book.title, "Test Book") self.assertEqual(book.author.name, "Test Author") -
集成测试
python复制from django.urls import reverse from rest_framework.test import APITestCase class BookAPITest(APITestCase): def setUp(self): self.author = Author.objects.create(name="API Author") self.book = Book.objects.create( title="API Book", author=self.author, price=39.99 ) def test_book_list(self): url = reverse('book-list') response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 1) -
端到端测试
python复制from selenium import webdriver from django.contrib.staticfiles.testing import StaticLiveServerTestCase class BookUITest(StaticLiveServerTestCase): @classmethod def setUpClass(cls): super().setUpClass() cls.browser = webdriver.Chrome() cls.browser.implicitly_wait(10) @classmethod def tearDownClass(cls): cls.browser.quit() super().tearDownClass() def test_book_list_page(self): self.browser.get(f"{self.live_server_url}/books/") self.assertIn("Books", self.browser.title)
CI/CD流水线示例
yaml复制# .github/workflows/django.yml
name: Django CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:13
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
DJANGO_SECRET_KEY: testkey
run: |
python manage.py test
8. Django项目演进与架构升级
8.1 从单体到模块化
演进路径:
-
基础阶段:所有代码在单个应用中
code复制myproject/ ├── settings.py ├── urls.py ├── models.py # 所有模型 └── views.py # 所有视图 -
功能拆分:按功能划分应用
code复制myproject/ ├── apps/ │ ├── users/ │ ├── products/ │ └── orders/ └── config/ ├── settings/ └── urls.py -
服务化准备:提取核心功能为独立包
code复制myproject/ ├── core/ # 通用功能 │ ├── authentication/ │ ├── utils/ │ └── middleware/ ├── services/ # 业务服务层 │ ├── payment/ │ └── notification/ └── apps/ # 前端交互层 ├── web/ └── api/
8.2 性能扩展策略
垂直扩展:
- 升级服务器配置(CPU、内存)
- 使用更快的数据库(如PostgreSQL优化配置)
- 增加缓存层(Redis集群)
水平扩展:
-
数据库扩展
- 读写分离:配置多个数据库路由
python复制# settings.py DATABASE_ROUTERS = ['path.to.PrimaryReplicaRouter'] DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'primary_db', # ... }, 'replica': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'replica_db', # ... } } - 分库分表:使用django-sharding等库
- 读写分离:配置多个数据库路由
-
应用层扩展
- 无状态设计:确保应用实例可互换
- 会话外部化:使用Redis存储会话
python复制SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "default"
-
异步任务处理
python复制# tasks.py from celery import Celery from django.core.mail import send_mail app = Celery('myproject') @app.task(bind=True, max_retries=3) def send_welcome_email(self, user_id): try: user = User.objects.get(id=user_id) send_mail( 'Welcome', 'Thank you for registering', 'noreply@example.com', [user.email], fail_silently=False, ) except Exception as exc: self.retry(exc=exc, countdown=60)
8.3 现代化改造策略
1. 异步支持升级
python复制# Django 3.1+ 异步视图
from django.http import JsonResponse
from asgiref.sync import sync_to_async
async def book_detail(request, pk):
try:
book = await sync_to_async(Book.objects.get)(pk=pk)
data = {
'title': book.title,
'author': book.author.name
}
return JsonResponse(data)
except Book.DoesNotExist:
return JsonResponse({'error': 'Not found'}, status=404)
2. 类型提示支持
python复制from django.db import models
from typing import Optional, List
from django.http import HttpRequest, HttpResponse
class Book(models.Model):
title: models.CharField = models.CharField(max_length=200)
author: models.ForeignKey = models.ForeignKey('Author', on_delete=models.CASCADE)
@classmethod
def get_popular_books(cls) -> models.QuerySet['Book']:
return cls.objects.filter