1. Django项目二次开发实战指南
作为Python生态中最成熟的Web框架之一,Django在快速开发方面有着无可比拟的优势。但很多开发者在完成第一个Django项目后,面对二次开发时常常陷入"知道基础但不知如何深化"的困境。本文将基于一个典型的二次开发场景,分享如何系统性地优化和扩展现有Django项目。
提示:本文假设读者已经完成过基础Django项目开发,熟悉MTV架构和基本操作流程。
1.1 项目现状分析
典型的二次开发场景通常具备以下特征:
- 已有基础功能框架但需要新增业务模块
- 数据库模型需要扩展但需保持历史数据兼容
- 性能瓶颈开始显现需要优化
- 代码组织混乱需要重构
以电商系统为例,初始版本可能只实现了用户注册和商品展示,二次开发时需要加入评论系统、购物车、订单管理等复杂功能。这时就需要考虑:
python复制# 初始模型可能只有简单的商品模型
class Goods(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
# 二次开发需要扩展关联模型
class Comment(models.Model):
goods = models.ForeignKey(Goods, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
1.2 开发环境配置要点
二次开发首先要确保环境一致性:
- 使用virtualenv隔离环境:
bash复制python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate.bat # Windows
- 依赖管理最佳实践:
- 使用pip-tools管理依赖版本
- 生成requirements.txt和requirements-dev.txt
- 示例操作流程:
bash复制pip install pip-tools
pip-compile requirements.in # 生成正式环境依赖
pip-compile requirements-dev.in # 开发环境额外依赖
- 解决常见环境问题:
- 当出现"No module named 'comment'"这类错误时:
- 检查INSTALLED_APPS是否注册了新创建的app
- 确保app目录下有__init__.py文件
- 在PyCharm等IDE中标记项目根目录为Sources Root
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Django项目深度优化方案
2.1 数据库查询优化实战
随着数据量增长,N+1查询问题会成为性能杀手。以下是几种实测有效的优化方案:
- select_related和prefetch_related的正确使用:
python复制# 低效写法(产生N+1查询)
comments = Comment.objects.all()
for c in comments:
print(c.user.username) # 每次循环都查询user表
# 优化方案
comments = Comment.objects.select_related('user').all()
- 使用django-debug-toolbar定位慢查询:
python复制# settings.py
INSTALLED_APPS += ['debug_toolbar']
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
# 开发环境配置
INTERNAL_IPS = ['127.0.0.1']
DEBUG_TOOLBAR_CONFIG = {
'SHOW_TOOLBAR_CALLBACK': lambda request: True
}
- 数据库索引优化示例:
python复制class Comment(models.Model):
# 添加索引的两种方式
created_at = models.DateTimeField(db_index=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
indexes = [
models.Index(fields=['user', 'created_at']),
]
2.2 缓存策略实施指南
Django提供了多级缓存方案,根据业务特点选择合适的策略:
- 视图级缓存:
python复制from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 缓存15分钟
def product_detail(request, pk):
...
- 模板片段缓存:
html复制{% load cache %}
{% cache 500 sidebar %}
<!-- 侧边栏内容 -->
{% endcache %}
- 低级缓存API使用:
python复制from django.core.cache import cache
def get_popular_products():
key = 'popular_products'
result = cache.get(key)
if not result:
result = Goods.objects.order_by('-views')[:10]
cache.set(key, result, timeout=3600)
return result
- 缓存后端选型对比:
| 后端类型 | 适用场景 | 优势 | 劣势 |
|---|---|---|---|
| LocMemCache | 开发环境 | 零配置 | 多进程不共享 |
| Redis | 生产环境 | 高性能/持久化 | 需要额外服务 |
| Memcached | 高并发读 | 内存效率高 | 无持久化 |
3. Django REST framework集成实践
3.1 DRF基础配置
- 安装与基础配置:
bash复制pip install djangorestframework
python复制# settings.py
INSTALLED_APPS += ['rest_framework']
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
]
}
- 序列化器设计技巧:
python复制class CommentSerializer(serializers.ModelSerializer):
user = serializers.SerializerMethodField()
class Meta:
model = Comment
fields = ['id', 'content', 'created_at', 'user']
def get_user(self, obj):
return {
'id': obj.user.id,
'username': obj.user.username
}
3.2 视图优化方案
- 通用视图使用模式:
python复制from rest_framework import generics
class CommentListCreateView(generics.ListCreateAPIView):
queryset = Comment.objects.select_related('user')
serializer_class = CommentSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(user=self.request.user)
- 自定义权限控制:
python复制from rest_framework import permissions
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.user == request.user
4. 项目重构与维护策略
4.1 应用模块化拆分
当项目规模扩大时,建议按功能拆分应用:
code复制myproject/
├── apps/
│ ├── account/
│ ├── goods/
│ └── comment/
├── config/
│ ├── settings/
│ │ ├── base.py
│ │ ├── dev.py
│ │ └── prod.py
│ └── urls.py
└── manage.py
关键配置调整:
python复制# settings/base.py
import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
INSTALLED_APPS = [
'account.apps.AccountConfig',
'goods.apps.GoodsConfig',
'comment.apps.CommentConfig',
]
4.2 自动化测试实施
- 测试文件结构建议:
code复制comment/
├── __init__.py
├── tests/
│ ├── __init__.py
│ ├── test_models.py
│ ├── test_views.py
│ └── test_serializers.py
├── models.py
└── views.py
- 模型测试示例:
python复制from django.test import TestCase
from comment.models import Comment
class CommentModelTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = User.objects.create(username='testuser')
cls.goods = Goods.objects.create(name='Test Product', price=100)
cls.comment = Comment.objects.create(
user=cls.user,
goods=cls.goods,
content='Test comment'
)
def test_content_max_length(self):
comment = Comment.objects.get(id=1)
max_length = comment._meta.get_field('content').max_length
self.assertEqual(max_length, 2000)
- API测试方案:
python复制from rest_framework.test import APITestCase
class CommentAPITest(APITestCase):
def setUp(self):
self.user = User.objects.create_user(
username='testuser',
password='testpass123'
)
self.client.force_authenticate(user=self.user)
def test_create_comment(self):
goods = Goods.objects.create(name='Test', price=100)
url = reverse('comment-list')
data = {'goods': goods.id, 'content': 'Test comment'}
response = self.client.post(url, data)
self.assertEqual(response.status_code, 201)
5. 生产环境部署要点
5.1 安全加固措施
- 关键安全设置:
python复制# settings/prod.py
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'
- 敏感信息管理:
- 使用python-dotenv管理环境变量
- 永远不要将SECRET_KEY提交到版本控制
- 定期轮换数据库凭证和API密钥
5.2 性能调优配置
- 静态文件处理:
python复制# settings/prod.py
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
- 中间件优化:
python复制MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
# 其他中间件...
]
- 数据库连接池配置:
python复制DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypass',
'HOST': 'localhost',
'PORT': '5432',
'OPTIONS': {
'connect_timeout': 3,
},
}
}
# 使用django-db-geventpool优化连接管理
DATABASES['default']['ENGINE'] = 'django_db_geventpool.backends.postgresql_psycopg2'
DATABASES['default']['CONN_MAX_AGE'] = 0
DATABASES['default']['OPTIONS']['MAX_CONNS'] = 20
6. 常见问题排查手册
6.1 模型关联问题
- 循环导入解决方案:
python复制# 错误示例:goods/models.py 和 comment/models.py 相互导入
# 正确做法:使用字符串引用
class Goods(models.Model):
# ...
def get_comments(self):
return self.comment_set.all() # 使用_set反向查询
# 或者在Meta中定义related_name
class Comment(models.Model):
goods = models.ForeignKey(
'goods.Goods',
on_delete=models.CASCADE,
related_name='comments'
)
- 迁移冲突处理流程:
bash复制# 查看迁移状态
python manage.py showmigrations
# 回滚到特定迁移
python manage.py migrate app_name 0002_previous_migration
# 解决冲突后重新生成迁移
rm app_name/migrations/0003_conflicting.py
python manage.py makemigrations
python manage.py migrate
6.2 模板渲染异常
- 上下文处理器缺失:
python复制# settings.py中确保包含
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
- 静态文件加载问题:
html复制<!-- 确保使用static模板标签 -->
{% load static %}
<img src="{% static 'images/logo.png' %}" alt="Logo">
<!-- 开发环境需要配置 -->
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
7. 项目扩展与进阶路线
7.1 异步任务处理
- Celery基础配置:
python复制# settings.py
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = TIME_ZONE
- 任务定义示例:
python复制# tasks.py
from celery import shared_task
from django.core.mail import send_mail
@shared_task
def send_comment_notification(comment_id):
comment = Comment.objects.get(id=comment_id)
send_mail(
'New Comment Notification',
f'New comment on {comment.goods.name}',
'noreply@example.com',
[comment.goods.user.email],
fail_silently=False,
)
7.2 微服务化改造
- 服务拆分策略:
- 用户服务:处理认证和个人资料
- 商品服务:管理商品目录和库存
- 订单服务:处理交易流程
- 评论服务:管理用户评价
- 服务间通信方案:
python复制# 使用requests直接调用(简单场景)
import requests
def get_product_details(product_id):
response = requests.get(
f'http://product-service/api/products/{product_id}',
timeout=3
)
return response.json()
# 使用gRPC(高性能场景)
# 安装:pip install grpcio grpcio-tools
- API网关配置示例(使用Django REST framework):
python复制# api_gateway/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
import requests
class ProductDetailView(APIView):
def get(self, request, pk):
# 调用商品服务
product = requests.get(f'http://product-service/api/products/{pk}').json()
# 调用评论服务
reviews = requests.get(
f'http://review-service/api/reviews/',
params={'product_id': pk}
).json()
return Response({
'product': product,
'reviews': reviews
})
8. 监控与日志体系建设
8.1 日志配置方案
- 生产环境日志配置:
python复制LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
},
'handlers': {
'file': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/django/app.log',
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5,
'formatter': 'verbose'
},
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
},
},
'root': {
'handlers': ['file', 'console'],
'level': 'INFO',
},
}
- 结构化日志实践:
python复制import structlog
structlog.configure(
processors=[
structlog.stdlib.filter_by_level,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer()
],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
)
logger = structlog.get_logger()
logger.info("user_login", user_id=request.user.id, ip=request.META['REMOTE_ADDR'])
8.2 性能监控集成
- APM工具配置(以Sentry为例):
python复制# settings.py
INSTALLED_APPS += ['sentry_sdk.integrations.django']
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(
dsn="your-dsn-here",
integrations=[DjangoIntegration()],
traces_sample_rate=1.0,
send_default_pii=True
)
- 自定义性能指标:
python复制from django.db import connection
from django.utils.deprecation import MiddlewareMixin
class QueryCountMiddleware(MiddlewareMixin):
def process_response(self, request, response):
count = len(connection.queries)
logger.info("query_count", count=count, path=request.path)
return response
- 健康检查端点:
python复制# urls.py
from django.http import JsonResponse
def health_check(request):
return JsonResponse({
'status': 'healthy',
'services': {
'database': check_database(),
'cache': check_cache(),
}
})
def check_database():
from django.db import connection
try:
connection.ensure_connection()
return {'status': 'up', 'version': connection.pg_version}
except Exception as e:
return {'status': 'down', 'error': str(e)}
9. 持续集成与部署流水线
9.1 GitHub Actions配置
- 基础测试流水线:
yaml复制# .github/workflows/test.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
pip install -r requirements-dev.txt
- name: Run tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
run: |
python manage.py test
- Docker构建部署:
yaml复制# .github/workflows/deploy.yml
name: Docker Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v2
with:
push: true
tags: yourusername/django-app:latest
9.2 自动化部署脚本
- 服务器初始化脚本:
bash复制#!/bin/bash
# init_server.sh
# 更新系统
apt update && apt upgrade -y
# 安装基础依赖
apt install -y \
python3-pip \
python3-dev \
libpq-dev \
nginx \
redis-server \
postgresql \
postgresql-contrib
# 配置PostgreSQL
sudo -u postgres psql -c "CREATE DATABASE myproject;"
sudo -u postgres psql -c "CREATE USER myprojectuser WITH PASSWORD 'mypassword';"
sudo -u postgres psql -c "ALTER ROLE myprojectuser SET client_encoding TO 'utf8';"
sudo -u postgres psql -c "ALTER ROLE myprojectuser SET default_transaction_isolation TO 'read committed';"
sudo -u postgres psql -c "ALTER ROLE myprojectuser SET timezone TO 'UTC';"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE myproject TO myprojectuser;"
# 安装Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
usermod -aG docker $USER
- 零停机部署方案:
python复制# deploy.py
import os
import subprocess
from datetime import datetime
def deploy():
# 拉取最新代码
subprocess.run(['git', 'pull'])
# 安装依赖
subprocess.run(['pip', 'install', '-r', 'requirements.txt'])
# 收集静态文件
subprocess.run(['python', 'manage.py', 'collectstatic', '--noinput'])
# 数据库迁移
subprocess.run(['python', 'manage.py', 'migrate'])
# 重载服务
timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
subprocess.run(['docker', 'compose', 'up', '-d', '--build'])
# 清理旧镜像
subprocess.run(['docker', 'system', 'prune', '-f'])
if __name__ == '__main__':
deploy()
10. 前端集成与现代化改造
10.1 Django与Vue.js集成
- 前后端分离配置:
python复制# settings.py
CORS_ALLOWED_ORIGINS = [
"http://localhost:8080",
"http://127.0.0.1:8080",
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}
- JWT认证配置:
python复制# settings.py
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
}
10.2 静态资源优化
- Webpack集成方案:
javascript复制// webpack.config.js
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
entry: {
app: './frontend/src/main.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'static/dist')
},
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
}
]
},
plugins: [
new VueLoaderPlugin()
]
}
- Django模板集成:
html复制{% load static %}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="{% static 'dist/css/app.css' %}">
</head>
<body>
<div id="app"></div>
<script src="{% static 'dist/js/app.bundle.js' %}"></script>
</body>
</html>
11. 国际化和本地化实践
11.1 多语言支持配置
- 基础配置:
python复制# settings.py
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LOCALE_PATHS = [
os.path.join(BASE_DIR, 'locale'),
]
LANGUAGES = [
('en', _('English')),
('zh-hans', _('Simplified Chinese')),
]
- 翻译标记示例:
python复制from django.utils.translation import gettext as _
class Comment(models.Model):
content = models.TextField(_('content'))
class Meta:
verbose_name = _('comment')
verbose_name_plural = _('comments')
- 模板翻译:
html复制{% load i18n %}
<h1>{% trans "Welcome to our store" %}</h1>
<p>{% blocktrans with name=user.username %}Hello {{ name }}{% endblocktrans %}</p>
11.2 本地化内容管理
- 动态内容翻译方案:
python复制# models.py
from django.db import models
class TranslatableModel(models.Model):
class Meta:
abstract = True
def get_translated_field(self, field_name, language):
translation = self.translations.filter(
language=language,
field=field_name
).first()
return translation.value if translation else getattr(self, field_name)
class Product(TranslatableModel):
name = models.CharField(max_length=100)
description = models.TextField()
class ProductTranslation(models.Model):
product = models.ForeignKey(Product, related_name='translations', on_delete=models.CASCADE)
language = models.CharField(max_length=10)
field = models.CharField(max_length=64)
value = models.TextField()
class Meta:
unique_together = ('product', 'language', 'field')
- 管理界面集成:
python复制# admin.py
from django.contrib import admin
class ProductTranslationInline(admin.TabularInline):
model = ProductTranslation
extra = 1
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
inlines = [ProductTranslationInline]
list_display = ['name', 'get_description']
def get_description(self, obj):
return obj.get_translated_field('description', 'zh-hans')
get_description.short_description = 'Description'
12. 项目文档与知识管理
12.1 自动化文档生成
- API文档生成(drf-yasg):
python复制# urls.py
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="API Documentation",
default_version='v1',
description="Project API docs",
),
public=True,
)
urlpatterns = [
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
- 模型文档生成(django-extensions):
bash复制python manage.py graph_models -a -g -o models.png
12.2 项目知识库建设
- 文档结构建议:
code复制docs/
├── ARCHITECTURE.md # 架构设计
├── API_GUIDE.md # API开发指南
├── DEPLOYMENT.md # 部署手册
├── DEVELOPMENT.md # 开发环境配置
└── OPERATION.md # 运维手册
- 文档编写规范:
- 使用Markdown格式
- 包含变更历史记录
- 关键决策记录(ADR)
- 故障处理手册
- API变更日志
- 文档自动化检查:
yaml复制# .github/workflows/docs.yml
name: Docs Check
on: [push, pull_request]
jobs:
markdownlint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: reviewdog/action-markdownlint@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
13. 团队协作与代码质量管理
13.1 Git工作流规范
- 分支策略:
- main:生产环境代码
- staging:预发布环境
- feature/*:功能开发分支
- hotfix/*:紧急修复分支
- 提交信息规范:
code复制<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
类型说明:
- feat:新功能
- fix:错误修复
- docs:文档变更
- style:代码格式
- refactor:代码重构
- test:测试相关
- chore:构建/依赖
13.2 代码质量保障
- 预提交钩子配置:
yaml复制# .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: debug-statements
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
- 代码检查配置:
ini复制# .flake8
[flake8]
max-line-length = 88
extend-ignore = E203
exclude =
.git,
__pycache__,
migrations,
venv
- 测试覆盖率配置:
ini复制# .coveragerc
[run]
source = .
omit =
*/tests/*
*/migrations/*
*/__init__.py
*/admin.py
*/apps.py
*/settings/*
[report]
show_missing = True
skip_covered = True
exclude_lines =
pragma: no cover
def __str__
raise NotImplementedError
14. 安全加固进阶指南
14.1 常见漏洞防护
- SQL注入防护:
- 始终使用ORM或参数化查询
- 禁止直接拼接SQL语句
- 定期进行安全扫描
- XSS防护措施:
python复制# settings.py
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
# 模板中自动转义
{{ user_input|escape }}
- CSRF防护增强:
python复制# settings.py
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SAMESITE = 'Strict'
CSRF_TRUSTED_ORIGINS = ['https://yourdomain.com']
14.2 安全审计实施
- 依赖安全检查:
bash复制pip install safety
safety check --full-report
- Django安全检查:
bash复制python manage.py check --deploy
- 自动化安全扫描:
yaml复制# .github/workflows/security.yml
name: Security Scan
on: [push, schedule]
jobs:
bandit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run Bandit
uses: reviewdog/action-bandit@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
15. 性能调优实战技巧
15.1 数据库高级优化
- 查询分析工具:
python复制# 使用django-silk分析性能
INSTALLED_APPS += ['silk']
MIDDLEWARE += ['silk.middleware.SilkyMiddleware']
# 配置采样率
SILKY_PYTHON_PROFILER = True
SILKY_PYTHON_PROFILER_BINARY = True
SILKY_MAX_RECORDED_REQUESTS = 10**4
- 分库分表策略:
python复制# 使用django-router实现分库
DATABASE_ROUTERS = ['path.to.PrimaryReplicaRouter']
class PrimaryReplicaRouter:
def db_for_read(self, model, **hints):
return 'replica'
def db_for_write(self, model, **hints):
return 'default'
def allow_relation(self, obj1, obj2, **hints):
return True
15.2 缓存高级应用
- 缓存失效策略:
python复制from django.core.cache import caches
def get_with_fallback(key, func, timeout=300):
cache = caches['default']
data = cache.get(key)
if data is None:
data = func()
cache.set(key, data, timeout)
# 异步更新缓存
async_update.delay(key, func.__name__)
return data
- 分布式锁实现:
python复制import redis
from contextlib import contextmanager
redis_client = redis.Redis()
@contextmanager
def redis_lock(lock_name, timeout=10):
try:
# 获取锁
acquired = redis_client.set(
lock_name, '1',
nx=True,
ex=timeout
)
if acquired:
yield True
else:
yield False
finally:
# 释放锁
redis_client.delete(lock_name)
16. 项目升级与迁移策略
16.1 Django版本升级
- 升级检查清单:
- 使用
python -Wa manage.py test运行测试 - 检查弃用警告
- 查看Django发布说明中的向后不兼容变更
- 逐步升级(如2.2 → 3.0 → 3.1 → ...)
- 自动化升级工具:
bash复制pip install django-upgrade
django-upgrade --target-version 3.2 path/to/project
16.2 数据迁移方案
- 大规模数据迁移:
python复制from django.core.management.base import BaseCommand
from django.db import transaction
class Command(BaseCommand):
help = 'Migrate old data to new schema'
def handle(self, *args, **options):
from old_app.models import OldModel
from new_app.models import NewModel
batch_size = 1000
total = OldModel.objects.count()
for i in range(0, total, batch_size):
with transaction.atomic():
old_objs = OldModel.objects.all()[i:i+batch_size]
new_objs = [
NewModel(
field1=o.field1,
field2=o.field2,
)
for o in old_objs
]
NewModel.objects.bulk_create(new_objs)
self.stdout.write(f'Processed {min(i+batch_size, total)}/{total}')
- 零停机迁移步骤:
- 新老系统并行运行
- 实现数据双向同步
- 逐步将读流量切到新系统
- 最终将写流量切到新系统
- 下线
