1. Django项目搭建与ORM基础
1.1 Django框架概述
Django作为Python生态中最成熟的Web框架之一,其设计哲学强调"不重复造轮子"和"快速开发"。我在实际项目中使用Django已有五年时间,它最吸引我的就是其内置的ORM系统。这个ORM不仅让我们摆脱了手写SQL的繁琐,更重要的是提供了数据库无关的抽象层。
举个例子,当我们需要从MySQL迁移到PostgreSQL时,只需修改settings.py中的数据库配置,几乎不需要改动模型代码。这种便利性在长期维护的项目中尤为重要。
1.2 开发环境准备
创建隔离的Python环境是专业开发的必备步骤。我强烈建议使用virtualenv而不是全局环境,这里分享几个实用技巧:
bash复制# 创建虚拟环境时指定Python版本(重要!)
python3.8 -m venv venv
# Windows下激活的小技巧
# 如果直接执行activate报错,可以尝试:
.\venv\Scripts\activate.ps1
# 安装Django时固定版本(避免后续版本兼容问题)
pip install django==3.2.12
注意:很多新手会忽略Python版本的问题。Django 3.2.x系列是LTS版本,支持到2024年,建议新项目都基于这个版本开始。
2. 项目结构与核心配置
2.1 合理的项目布局
通过20+个Django项目的实践,我总结出这样的项目结构最利于长期维护:
code复制myproject/
├── apps/ # 所有应用放在这里
│ ├── book/
│ └── movie/
├── config/ # 原项目目录改名为config
│ ├── settings/
│ │ ├── base.py
│ │ ├── dev.py
│ │ └── prod.py
│ └── urls.py
├── static/ # 静态文件
└── manage.py
这种结构的关键优势在于:
- 应用集中管理,避免散落在项目根目录
- 配置按环境分离,降低生产环境配置泄露风险
- 静态资源统一管理,便于CDN部署
2.2 数据库配置详解
MySQL配置中有几个容易踩坑的参数:
python复制DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_douban',
'USER': 'root',
'PASSWORD': 'your_password',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4', # 支持emoji等特殊字符
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", # 严格模式
'connect_timeout': 5, # 连接超时设置
}
}
}
特别提醒:
- 一定要设置sql_mode为STRICT_TRANS_TABLES,否则可能出现数据静默截断
- utf8mb4是MySQL真正的UTF-8编码,常规utf8只能存储3字节字符
3. 模型设计与ORM实践
3.1 模型定义最佳实践
基于大量项目经验,我总结出模型定义的几个黄金准则:
python复制from django.db import models
from django.core.validators import MinValueValidator
class Book(models.Model):
title = models.CharField(
max_length=100,
verbose_name="书名",
help_text="书籍的完整标题,不超过100字符"
)
author = models.CharField(
max_length=100,
db_index=True, # 常查询的字段加索引
verbose_name="作者"
)
price = models.DecimalField(
max_digits=5,
decimal_places=2,
validators=[MinValueValidator(0)], # 价格不能为负
verbose_name="价格"
)
pub_date = models.DateField(
auto_now_add=True,
verbose_name="出版日期"
)
# 关系字段命名技巧:使用关联模型名的小写
category = models.ForeignKey(
'Category',
on_delete=models.PROTECT, # 保护模式防止误删
related_name='books', # 反向查询名称
verbose_name="分类"
)
class Meta:
db_table = 'library_book' # 显式指定表名
ordering = ['-pub_date'] # 默认排序
indexes = [
models.Index(fields=['title', 'author']), # 复合索引
]
def __str__(self):
return f"{self.title} ({self.author})"
关键经验:
- 所有字段都应设置verbose_name,这对admin后台和文档生成很重要
- 外键优先使用PROTECT而非CASCADE,避免级联删除导致数据意外丢失
- 为常用查询字段添加db_index提升性能
- 实现__str__方法便于调试和admin展示
3.2 迁移操作进阶技巧
迁移是Django ORM最强大的特性之一,但也是新手最容易出问题的地方。分享几个实用命令:
bash复制# 查看生成的SQL语句(重要!部署前必看)
python manage.py sqlmigrate book 0001
# 数据迁移(现有数据表导入)
python manage.py inspectdb > models.py # 自动生成模型
# 合并迁移文件(当分支合并出现冲突时)
python manage.py makemigrations --merge
# 安全删除迁移文件的正确流程
1. 备份数据库
2. python manage.py migrate app_name zero # 回滚所有迁移
3. 删除migrations目录下所有文件
4. python manage.py makemigrations
5. python manage.py migrate
警告:千万不要直接删除迁移文件而不执行回滚!这会导致数据库状态与迁移记录不同步。
4. 视图与路由设计
4.1 路由拆分模式
对于中型以上项目,我推荐这种路由组织方式:
python复制# config/urls.py (主路由)
from django.urls import include, path
urlpatterns = [
path('api/v1/', include([
path('books/', include('apps.book.urls')),
path('movies/', include('apps.movie.urls')),
])),
path('admin/', admin.site.urls),
]
python复制# apps/book/urls.py (子路由)
from django.urls import path
from . import views
app_name = 'book'
urlpatterns = [
path('', views.BookListView.as_view(), name='list'),
path('<int:pk>/', views.BookDetailView.as_view(), name='detail'),
path('search/', views.BookSearchView.as_view(), name='search'),
]
优势分析:
- API版本化设计,便于后续升级
- 每个应用独立管理自己的路由
- 使用类视图更易于维护和扩展
4.2 类视图实践
基于函数的视图在小项目中可行,但类视图更适合复杂业务:
python复制from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
class BookListView(LoginRequiredMixin, ListView):
model = Book
template_name = 'book/list.html'
context_object_name = 'books'
paginate_by = 20
def get_queryset(self):
queryset = super().get_queryset()
if 'category' in self.request.GET:
queryset = queryset.filter(
category_id=self.request.GET['category']
)
return queryset.order_by('-pub_date')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['categories'] = Category.objects.all()
return context
类视图的核心优势:
- 内置常用功能(分页、权限控制等)
- 清晰的代码结构(一个方法只做一件事)
- 易于通过Mixin扩展功能
5. ORM查询优化
5.1 查询性能优化
Django ORM虽然方便,但不当使用会导致严重性能问题。以下是关键优化点:
python复制# 反例:N+1查询问题
books = Book.objects.all()
for book in books:
print(book.category.name) # 每次循环都查询数据库
# 正解:使用select_related
books = Book.objects.select_related('category').all()
# 多对多关系使用prefetch_related
authors = Author.objects.prefetch_related('books').all()
# 只获取需要的字段
books = Book.objects.only('title', 'author')
# 使用values()获取字典结果
books = Book.objects.filter(
pub_date__year=2023
).values('title', 'author')
5.2 复杂查询技巧
对于复杂查询,我通常采用这些模式:
python复制from django.db.models import Q, Count, F
# Q对象实现复杂条件
Book.objects.filter(
Q(title__icontains='python') | Q(author__icontains='python'),
pub_date__gte='2020-01-01'
)
# 注解和聚合
from django.db.models import Avg
Category.objects.annotate(
book_count=Count('books'),
avg_price=Avg('books__price')
)
# F表达式避免竞态条件
Book.objects.filter(stock__gt=0).update(
stock=F('stock') - 1
)
6. 常见问题解决方案
6.1 外键操作陷阱
外键操作中最常见的三个坑及解决方案:
-
循环导入问题
当模型A引用模型B,模型B又引用模型A时:python复制# 使用字符串引用代替直接导入 category = models.ForeignKey( 'Category', # 使用字符串 on_delete=models.CASCADE ) -
批量创建性能问题
python复制# 反例:每次save都产生一次查询 for item in data: Book.objects.create(**item) # 正解:使用bulk_create books = [Book(**item) for item in data] Book.objects.bulk_create(books) -
跨数据库事务
python复制from django.db import transaction with transaction.atomic(): book = Book.objects.create(...) Inventory.objects.create(book=book, count=10) # 所有操作要么全部成功,要么全部回滚
6.2 生产环境建议
经过多次项目部署,这些经验特别重要:
-
连接池配置
Django默认不启用数据库连接池,高并发下会导致连接耗尽:python复制DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydb', 'USER': 'myuser', 'PASSWORD': 'mypassword', 'HOST': 'localhost', 'PORT': '5432', 'CONN_MAX_AGE': 300, # 连接存活时间(秒) 'OPTIONS': { 'application_name': 'myapp' } } } -
索引优化
通过explain分析慢查询:python复制from django.db import connection queryset = Book.objects.filter(author='某作者') print(queryset.explain()) -
读写分离
配置多数据库路由:python复制class PrimaryReplicaRouter: def db_for_read(self, model, **hints): return 'replica' def db_for_write(self, model, **hints): return 'default'
7. 项目实战:图书管理系统
7.1 完整模型设计
结合前面所有经验,我们设计一个增强版图书管理系统:
python复制from django.db import models
from django.utils.translation import gettext_lazy as _
class Publisher(models.Model):
name = models.CharField(_('名称'), max_length=100)
address = models.TextField(_('地址'))
website = models.URLField(_('网站'))
class Meta:
verbose_name = _('出版社')
verbose_name_plural = _('出版社')
class Author(models.Model):
name = models.CharField(_('姓名'), max_length=100)
email = models.EmailField(_('邮箱'), blank=True)
birth_date = models.DateField(_('出生日期'), null=True)
class Meta:
verbose_name = _('作者')
verbose_name_plural = _('作者')
class Category(models.Model):
name = models.CharField(_('名称'), max_length=50, unique=True)
description = models.TextField(_('描述'), blank=True)
class Meta:
verbose_name = _('分类')
verbose_name_plural = _('分类')
class Book(models.Model):
class Language(models.TextChoices):
CN = 'zh', _('中文')
EN = 'en', _('英文')
JA = 'ja', _('日文')
title = models.CharField(_('书名'), max_length=200)
isbn = models.CharField(_('ISBN'), max_length=13, unique=True)
language = models.CharField(
_('语言'),
max_length=2,
choices=Language.choices,
default=Language.CN
)
authors = models.ManyToManyField(Author, verbose_name=_('作者'))
publisher = models.ForeignKey(
Publisher,
on_delete=models.PROTECT,
verbose_name=_('出版社')
)
categories = models.ManyToManyField(Category, verbose_name=_('分类'))
publish_date = models.DateField(_('出版日期'))
price = models.DecimalField(
_('价格'),
max_digits=6,
decimal_places=2
)
stock = models.PositiveIntegerField(_('库存'), default=0)
class Meta:
verbose_name = _('图书')
verbose_name_plural = _('图书')
indexes = [
models.Index(fields=['title']),
models.Index(fields=['isbn']),
]
ordering = ['-publish_date']
def __str__(self):
return f"{self.title} ({self.isbn})"
7.2 高级查询接口
实现一个带过滤、排序和分页的图书查询接口:
python复制from rest_framework import generics
from django_filters import rest_framework as filters
from .models import Book
from .serializers import BookSerializer
class BookFilter(filters.FilterSet):
min_price = filters.NumberFilter(field_name="price", lookup_expr='gte')
max_price = filters.NumberFilter(field_name="price", lookup_expr='lte')
author = filters.CharFilter(field_name="authors__name", lookup_expr='icontains')
category = filters.CharFilter(field_name="categories__name")
class Meta:
model = Book
fields = ['language', 'publisher']
class BookListView(generics.ListAPIView):
queryset = Book.objects.select_related('publisher')\
.prefetch_related('authors', 'categories')
serializer_class = BookSerializer
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = BookFilter
def get_queryset(self):
queryset = super().get_queryset()
# 自定义排序
sort_by = self.request.query_params.get('sort', '-publish_date')
return queryset.order_by(sort_by)
这个接口支持:
- 按价格区间过滤
- 按作者名模糊搜索
- 按分类精确过滤
- 多字段排序
- 自动分页(通过DRF配置)
7.3 性能监控与优化
在生产环境中,我通常会添加这些监控措施:
-
查询监控
python复制# settings.py LOGGING = { 'version': 1, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'level': 'DEBUG', 'handlers': ['console'], }, }, } -
缓存策略
python复制from django.core.cache import cache def get_popular_books(): key = 'popular_books' result = cache.get(key) if not result: result = Book.objects.annotate( sales=Count('orders') ).order_by('-sales')[:10] cache.set(key, result, timeout=3600) # 缓存1小时 return result -
性能分析工具
- django-debug-toolbar:开发环境使用
- silk:生产环境性能分析
- sentry:错误监控
8. 项目部署建议
8.1 安全配置
这些安全设置每个Django项目都应该有:
python复制# settings.py
SECURE_SSL_REDIRECT = True # 强制HTTPS
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000 # 1年HSTS
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
X_FRAME_OPTIONS = 'DENY'
8.2 生产环境配置
与开发环境不同,生产环境需要特别注意:
python复制# 使用环境变量管理敏感配置
import os
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True'
# 数据库连接池配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT'),
'CONN_MAX_AGE': 300,
'OPTIONS': {
'sslmode': 'require',
},
}
}
# 静态文件配置
STATIC_ROOT = '/var/www/static/'
STATIC_URL = '/static/'
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = '/media/'
8.3 部署流程
经过多次项目部署,这个流程最可靠:
-
准备阶段
bash复制# 生成requirements.txt pip freeze > requirements.txt # 收集静态文件 python manage.py collectstatic # 数据库迁移 python manage.py migrate -
使用Gunicorn
bash复制gunicorn --workers 4 --threads 2 --bind 0.0.0.0:8000 config.wsgi -
Nginx配置示例
nginx复制upstream django_app { server 127.0.0.1:8000; } server { listen 80; server_name example.com; location /static/ { alias /var/www/static/; } location /media/ { alias /var/www/media/; } location / { proxy_pass http://django_app; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
9. 持续集成与测试
9.1 自动化测试策略
Django的测试框架非常强大,合理的测试结构应该是:
code复制tests/
├── __init__.py
├── factories.py # 测试数据工厂
├── conftest.py # pytest配置
├── test_models.py
├── test_views.py
└── test_apis.py
示例测试用例:
python复制import pytest
from django.urls import reverse
from rest_framework.test import APIClient
from .factories import BookFactory
@pytest.mark.django_db
class TestBookAPI:
def setup_method(self):
self.client = APIClient()
self.book = BookFactory()
def test_book_list(self):
url = reverse('book-list')
response = self.client.get(url)
assert response.status_code == 200
assert len(response.data) >= 1
def test_book_detail(self):
url = reverse('book-detail', args=[self.book.id])
response = self.client.get(url)
assert response.status_code == 200
assert response.data['title'] == self.book.title
9.2 CI/CD配置
GitLab CI示例配置:
yaml复制stages:
- test
- deploy
test:
stage: test
image: python:3.8
services:
- postgres:13
variables:
POSTGRES_DB: test_db
POSTGRES_USER: runner
POSTGRES_PASSWORD: ""
before_script:
- pip install -r requirements.txt
script:
- python manage.py test --noinput
deploy_prod:
stage: deploy
image: python:3.8
only:
- master
script:
- apt-get update && apt-get install -y sshpass
- sshpass -p "$DEPLOY_PASSWORD" ssh -o StrictHostKeyChecking=no deploy@server "
cd /opt/app &&
git pull &&
pip install -r requirements.txt &&
python manage.py migrate &&
sudo systemctl restart gunicorn
"
10. 项目扩展建议
10.1 添加全文搜索
使用Django Haystack实现:
python复制# search_indexes.py
from haystack import indexes
from .models import Book
class BookIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr='title')
author = indexes.CharField(model_attr='authors__name')
def get_model(self):
return Book
def index_queryset(self, using=None):
return self.get_model().objects.all()
10.2 实现推荐系统
基于用户行为的简单推荐:
python复制from django.db.models import Count
def get_recommendations(user):
# 获取用户购买过的书籍分类
user_categories = user.purchases.values_list(
'book__categories__id', flat=True
).distinct()
# 获取同分类的热门书籍
return Book.objects.filter(
categories__id__in=user_categories
).annotate(
purchase_count=Count('purchases')
).order_by('-purchase_count')[:5]
10.3 异步任务处理
使用Celery处理耗时操作:
python复制# tasks.py
from celery import shared_task
from django.core.mail import send_mail
@shared_task
def send_book_notification(book_id, recipient_list):
book = Book.objects.get(id=book_id)
subject = f"新书上架:{book.title}"
message = f"《{book.title}》已上架,价格:{book.price}元"
send_mail(
subject,
message,
'noreply@example.com',
recipient_list
)
调用方式:
python复制# 在视图中异步发送邮件
send_book_notification.delay(book.id, ['user@example.com'])
11. 项目维护与监控
11.1 日志配置
生产环境推荐日志配置:
python复制LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'file': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': '/var/log/django/app.log',
'when': 'midnight',
'backupCount': 30,
},
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
}
},
'loggers': {
'django': {
'handlers': ['file'],
'level': 'INFO',
},
'myapp': {
'handlers': ['file', 'mail_admins'],
'level': 'INFO',
},
},
}
11.2 健康检查
添加健康检查端点:
python复制# urls.py
from django.http import JsonResponse
def health_check(request):
from django.db import connection
try:
connection.ensure_connection()
return JsonResponse({'status': 'ok'})
except Exception as e:
return JsonResponse({'status': 'error'}, status=500)
urlpatterns = [
path('health/', health_check),
# ...其他路由
]
12. 项目文档化
12.1 API文档生成
使用drf-yasg自动生成Swagger文档:
python复制# urls.py
from drf_yasg import openapi
from drf_yasg.views import get_schema_view
schema_view = get_schema_view(
openapi.Info(
title="图书API",
default_version='v1',
),
public=True,
)
urlpatterns = [
path('swagger/', schema_view.with_ui('swagger')),
# ...其他路由
]
12.2 模型文档
使用django-model-utils自动生成模型文档:
python复制from model_utils import Choices
class Book(models.Model):
STATUS = Choices(
('draft', '草稿'),
('published', '已发布'),
('archived', '已归档')
)
status = models.CharField(
choices=STATUS,
default=STATUS.draft
)
13. 项目优化进阶
13.1 数据库读写分离
配置多数据库路由:
python复制# database_routers.py
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
def allow_migrate(self, db, app_label, model_name=None, **hints):
return db == 'default'
13.2 缓存优化
使用Redis作为缓存后端:
python复制CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
}
}
}
# 会话引擎也使用Redis
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
14. 项目安全加固
14.1 常见安全防护
python复制# settings.py
# 点击劫持防护
X_FRAME_OPTIONS = 'DENY'
# XSS防护
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
# CSRF防护
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SECURE = True
# 会话安全
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'Lax'
14.2 密码哈希设置
使用Argon2作为默认密码哈希器:
python复制PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
]
15. 项目国际化
15.1 多语言支持
python复制# models.py
from django.utils.translation import gettext_lazy as _
class Book(models.Model):
title = models.CharField(_('title'), max_length=100)
class Meta:
verbose_name = _('book')
verbose_name_plural = _('books')
15.2 本地化配置
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'),
]
16. 项目调试技巧
16.1 Django Debug Toolbar
配置方法:
python复制# settings.py
if DEBUG:
INSTALLED_APPS += ['debug_toolbar']
MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']
INTERNAL_IPS = ['127.0.0.1']
16.2 IPython调试
在视图中使用:
python复制from IPython import embed
def my_view(request):
# ...代码
embed() # 进入交互式调试
# ...代码
17. 项目依赖管理
17.1 使用pip-tools
工作流程:
bash复制# 创建requirements.in
echo "django==3.2.12" > requirements.in
# 生成requirements.txt
pip-compile requirements.in
# 同步环境
pip-sync requirements.txt
17.2 依赖更新策略
bash复制# 更新所有依赖
pip-compile --upgrade
# 更新特定包
pip-compile --upgrade-package django
18. 项目代码质量
18.1 代码检查工具
推荐工具链:
bash复制# 安装工具
pip install flake8 black isort mypy
# 使用示例
flake8 .
black .
isort .
mypy .
18.2 预提交钩子
.pre-commit-config.yaml示例:
yaml复制repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- repo: https://github.com/psf/black
rev: 21.12b0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
hooks:
- id: flake8
19. 项目团队协作
19.1 Git工作流
推荐工作流:
-
功能开发:
bash复制git checkout -b feature/xxx git commit -m "feat: add xxx" git push origin feature/xxx -
代码审查后合并:
bash复制
git checkout main git merge --no-ff feature/xxx git push origin main
19.2 提交信息规范
使用Angular风格:
code复制<type>(<scope>): <subject>
<body>
<footer>
常见type:
- feat:新功能
- fix:bug修复
- docs:文档变更
- style:代码格式
- refactor:重构
- test:测试相关
- chore:构建或辅助工具变更
20. 项目持续演进
20.1 技术债务管理
创建技术债务看板:
code复制TODO.md
--------
## 技术债务
### 高优先级
- [ ] 重构订单模块的支付流程
- [ ] 优化商品搜索性能
### 低优先级
- [ ] 统一日志格式
- [ ] 更新文档示例
20.2 版本升级策略
Django LTS版本升级路线:
- 测试环境验证
- 逐步升级依赖
- 运行测试套件
- 性能基准测试
- 生产环境灰度发布
21. 项目监控告警
21.1 性能监控
使用Prometheus + Grafana:
python复制# settings.py
INSTALLED_APPS += ['django_prometheus']
MIDDLEWARE = [
'django_prometheus.middleware.PrometheusBeforeMiddleware',
# ...其他中间件
'django_prometheus.middleware.PrometheusAfterMiddleware',
]
21.2 错误监控
使用Sentry:
python复制# settings.py
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
sentry_sdk.init(
dsn="YOUR_DSN",
integrations=[DjangoIntegration()],
traces_sample_rate=1.0,
send_default_pii=True
)
22. 项目备份策略
22.1 数据库备份
使用django-dbbackup:
bash复制# 安装
pip install django-dbbackup
# 配置
DBBACKUP_STORAGE = 'django.core.files.storage.FileSystemStorage'
DBBACKUP_STORAGE_OPTIONS = {'location': '/var/backups'}
# 执行备份
python manage.py dbbackup
22.2 媒体文件备份
使用rsync:
bash复制rsync -avz /var/www/media/ backup-server:/backups/media/
23. 项目扩展架构
23.1 微服务拆分
当项目变大时,可考虑拆分为:
- 用户服务
- 商品服务
- 订单服务
- 支付服务
使用gRPC或REST进行服务间通信。
23.2 前后端分离
完全分离架构:
code复制前端:React/Vue + Webpack
后端:Django REST Framework
通信:JSON API
部署:前端静态文件通过CDN分发
24. 项目性能调优
24.1 数据库索引优化
使用django-indexes:
python复制class Book(models.Model):
class Meta:
indexes = [
models.Index(fields=['title', 'author']),
models.Index(fields=['publish_date'], name='pub_date_idx'),
]
24.2 查询优化
使用django-query-profiler:
python复制# settings.py
MIDDLEWARE += ['query_profiler.client.middleware.QueryProfilerMiddleware']
25. 项目容器化部署
25.1 Docker配置
Dockerfile示例:
dockerfile复制FROM python:3.8
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "config.wsgi"]
25.2 docker-compose配置
docker-compose.yml示例:
yaml复制version: '3'
services:
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- db
volumes:
postgres_data:
26. 项目自动化测试
26.1 单元测试示例
python复制from django.test import TestCase
from .models import Book
class BookModelTest(TestCase):
@classmethod
def setUpTestData(cls