- 重复造轮子浪费时间:每个项目都要从头搭建用户认证、后台管理、权限控制等基础功能,开发周期长,代码质量参差不齐
- 前后端分离开发成本高:需要维护两套技术栈,API接口联调困难,跨域问题频发,小型团队难以承受
- 数据库操作繁琐易错:手动编写SQL语句容易引入SQL注入漏洞,复杂的关联查询代码冗长,维护困难
- 安全防护实现复杂:CSRF、XSS、SQL注入等Web安全威胁需要大量手动防护代码,稍有不慎就留下安全隐患
- 部署运维流程混乱:服务器配置、性能优化、监控告警等环节需要大量专业知识,项目上线后运维压力大
Django正是为解决这些痛点而生的全功能企业级Web框架。作为Python Web开发的事实标准,它提供"开箱即用"的一站式解决方案,内置ORM、Admin后台、用户认证、表单处理等核心功能,让开发者专注于业务逻辑,而不是重复的基础设施建设。无论是构建内容管理系统、电子商务平台还是企业内部门户,Django都能让你事半功倍。根据GitHub统计数据,Django拥有超过86000星标,是Python生态中最受欢迎的Web项目之一。Instagram、Mozilla、Pinterest等知名企业都在使用Django支撑核心业务,证明了其在大规模生产环境中的可靠性和稳定性。- 理解MTV架构精髓:掌握Django独有的Model-Template-View设计模式,学会合理的代码组织方式
- 精通ORM高级查询:告别手写SQL,通过Python对象操作数据库,实现高效安全的数据访问
- 掌握Admin后台定制:零代码搭建专业管理后台,满足复杂业务场景的定制化需求
- 解锁现代化开发特性:了解Django 6.0的新特性,包括内置后台任务、原生CSP支持、模板片段等
- 实战企业级应用开发:从需求分析到部署上线,完整构建一个内容管理系统
- 掌握性能优化技巧:缓存策略、数据库优化、异步处理,让你的应用高性能运行
Django是一个高级Python Web框架,由Adrian Holovaty和Simon Willison于2005年创建。它的名字来源于爵士吉他手Django Reinhardt,体现了框架的优雅和艺术性。Django的设计哲学可以概括为:- DRY原则:Don't Repeat Yourself,避免重复代码,提高开发效率
- 快速开发:提供完整的开箱即用功能,减少初始配置时间
- 安全性优先:内置多种安全防护机制,帮助开发者构建安全的Web应用
Django采用MTV(Model-Template-View)架构模式,这是对传统MVC模式的一种优化变体。在Django中:- Model:负责数据层,定义数据结构并与数据库交互
- 企业级应用:CRM客户关系管理、ERP企业资源规划、OA办公自动化
- 电子商务平台:B2C商城、B2B交易平台、在线支付系统
对于需要快速原型验证、团队协作开发、长期维护迭代的项目,Django都能提供强大的支持。Django的MTV架构是其设计哲学的核心体现,让我们通过代码示例来理解各层职责:# models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
classCategory(models.Model):
"""文章分类模型"""
name = models.CharField(max_length=100, unique=True, verbose_name="分类名称")
description = models.TextField(blank=True, verbose_name="分类描述")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
classMeta:
db_table = 'blog_categories'
verbose_name = '文章分类'
verbose_name_plural = '文章分类'
ordering = ['name']
def__str__(self):
return self.name
classArticle(models.Model):
"""文章模型"""
STATUS_CHOICES = [
('draft', '草稿'),
('published', '已发布'),
('archived', '已归档'),
]
title = models.CharField(max_length=200, verbose_name="文章标题")
content = models.TextField(verbose_name="文章内容")
category = models.ForeignKey(
Category,
on_delete=models.SET_NULL,
null=True,
related_name='articles',
verbose_name="所属分类"
)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
related_name='articles',
verbose_name="作者"
)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='draft',
verbose_name="状态"
)
published_at = models.DateTimeField(null=True, blank=True, verbose_name="发布时间")
created_at = datetimefield(auto_now_add=True, verbose_name="创建时间")
updated_at = datetimefield(auto_now=True, verbose_name="更新时间")
classMeta:
db_table = 'blog_articles'
verbose_name = '文章'
verbose_name_plural = '文章'
ordering = ['-published_at', '-created_at']
indexes = [
models.Index(fields=['status', 'published_at']),
models.Index(fields=['category', 'published_at']),
]
def__str__(self):
return self.title
defsave(self, *args, **kwargs):
"""自定义保存逻辑:发布时自动设置发布时间"""
if self.status == 'published'andnot self.published_at:
from django.utils import timezone
self.published_at = timezone.now()
super().save(*args, **kwargs)
# views.py
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView, CreateView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.urls import reverse_lazy
from django.contrib import messages
from django.utils import timezone
from .models import Article, Category
from .forms import ArticleForm
classArticleListView(ListView):
"""文章列表视图"""
model = Article
template_name = 'blog/article_list.html'
context_object_name = 'articles'
paginate_by = 10
defget_queryset(self):
"""重写查询集:只显示已发布的文章"""
queryset = super().get_queryset()
return queryset.filter(status='published').select_related('author', 'category')
defget_context_data(self, **kwargs):
"""添加上下文数据:分类列表"""
context = super().get_context_data(**kwargs)
context['categories'] = Category.objects.all()
return context
classArticleDetailView(DetailView):
"""文章详情视图"""
model = Article
template_name = 'blog/article_detail.html'
context_object_name = 'article'
defget_queryset(self):
"""重写查询集:只允许查看已发布的文章"""
return super().get_queryset().filter(status='published')
defget_context_data(self, **kwargs):
"""添加上下文数据:相关文章"""
context = super().get_context_data(**kwargs)
article = self.get_object()
context['related_articles'] = Article.objects.filter(
category=article.category,
status='published'
).exclude(id=article.id)[:5]
return context
classArticleCreateView(LoginRequiredMixin, CreateView):
"""创建文章视图"""
model = Article
form_class = ArticleForm
template_name = 'blog/article_form.html'
success_url = reverse_lazy('article_list')
defform_valid(self, form):
"""表单验证通过:自动设置作者"""
form.instance.author = self.request.user
messages.success(self.request, '文章创建成功!')
return super().form_valid(form)
classArticleUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
"""更新文章视图"""
model = Article
form_class = ArticleForm
template_name = 'blog/article_form.html'
permission_required = 'blog.change_article'
success_url = reverse_lazy('article_list')
defget_queryset(self):
"""重写查询集:作者只能编辑自己的文章"""
queryset = super().get_queryset()
ifnot self.request.user.has_perm('blog.change_article'):
queryset = queryset.filter(author=self.request.user)
return queryset
defform_valid(self, form):
"""表单验证通过:显示成功消息"""
messages.success(self.request, '文章更新成功!')
return super().form_valid(form)
<!-- templates/blog/article_list.html -->
{% extends 'base.html' %}
{% block title %}文章列表 - Python与AI智能研习社{% endblock %}
{% block content %}
<divclass="container-fluid">
<divclass="row">
<!-- 左侧分类导航 -->
<divclass="col-md-3">
<divclass="card mb-4">
<divclass="card-header bg-primary text-white">
<h5class="mb-0">文章分类</h5>
</div>
<divclass="card-body">
<divclass="list-group">
<ahref="{% url 'article_list' %}"class="list-group-item list-group-item-action {% if not current_category %}active{% endif %}">
全部文章
</a>
{% for category in categories %}
<ahref="{% url 'article_list_by_category' category.id %}"
class="list-group-item list-group-item-action {% if current_category.id == category.id %}active{% endif %}">
{{ category.name }}
<spanclass="badge bg-secondary float-end">{{ category.articles.count }}</span>
</a>
{% endfor %}
</div>
</div>
</div>
</div>
<!-- 右侧文章列表 -->
<divclass="col-md-9">
<divclass="card">
<divclass="card-header">
<divclass="d-flex justify-content-between align-items-center">
<h4class="mb-0">最新文章</h4>
{% if user.is_authenticated %}
<ahref="{% url 'article_create' %}"class="btn btn-primary">
<iclass="fas fa-plus"></i> 写文章
</a>
{% endif %}
</div>
</div>
<divclass="card-body">
{% if articles %}
<divclass="list-group">
{% for article in articles %}
<ahref="{% url 'article_detail' article.id %}"class="list-group-item list-group-item-action">
<divclass="d-flex w-100 justify-content-between">
<h5class="mb-1">{{ article.title }}</h5>
<smallclass="text-muted">{{ article.published_at|date:"Y-m-d H:i" }}</small>
</div>
<divclass="d-flex justify-content-between align-items-center">
<div>
<spanclass="badge bg-info">{{ article.category.name }}</span>
<spanclass="badge bg-success">{{ article.get_status_display }}</span>
</div>
<divclass="text-muted small">
<iclass="fas fa-user"></i> {{ article.author.username }}
<iclass="fas fa-eye ms-2"></i> {{ article.view_count }}
</div>
</div>
</a>
{% endfor %}
</div>
<!-- 分页 -->
{% if is_paginated %}
<navaria-label="文章分页"class="mt-4">
<ulclass="pagination justify-content-center">
{% if page_obj.has_previous %}
<liclass="page-item">
<aclass="page-link"href="?page={{ page_obj.previous_page_number }}">上一页</a>
</li>
{% endif %}
{% for num in paginator.page_range %}
{% if page_obj.number == num %}
<liclass="page-item active"><spanclass="page-link">{{ num }}</span></li>
{% else %}
<liclass="page-item"><aclass="page-link"href="?page={{ num }}">{{ num }}</a></li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<liclass="page-item">
<aclass="page-link"href="?page={{ page_obj.next_page_number }}">下一页</a>
</li>
{% endif %}
</ul>
</nav>
{% endif %}
{% else %}
<divclass="text-center py-5">
<iclass="fas fa-inbox fa-3x text-muted mb-3"></i>
<h5class="text-muted">暂无文章</h5>
<pclass="text-muted">快来发布第一篇文章吧!</p>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
2026年初发布的Django 6.0带来了多项重要改进,让我们逐一解析:# tasks.py
from django.tasks import task
from django.core.mail import send_mail
from django.tasks.backends.database import DatabaseBackend
@task(backend=DatabaseBackend)
defsend_welcome_email(user_id: int):
"""发送欢迎邮件任务"""
from django.contrib.auth import get_user_model
User = get_user_model()
try:
user = User.objects.get(id=user_id)
subject = '欢迎加入Python与AI智能研习社!'
message = f'亲爱的{user.username},感谢您注册我们的社区!'
from_email = 'noreply@python-ai.com'
recipient_list = [user.email]
send_mail(subject, message, from_email, recipient_list)
print(f'欢迎邮件已发送至 {user.email}')
except User.DoesNotExist:
print(f'用户 {user_id} 不存在')
# views.py中使用
from django.http import HttpResponse
from .tasks import send_welcome_email
defregister_user(request):
"""用户注册视图"""
# ... 用户注册逻辑
user_id = 123# 实际从数据库中获取
# 异步发送欢迎邮件
send_welcome_email.delay(user_id)
return HttpResponse('注册成功,欢迎邮件已安排发送!')
# settings.py
CSP_CONFIG = {
'default-src': ["'self'"],
'script-src': ["'self'", "'unsafe-inline'", "https://cdn.jsdelivr.net"],
'style-src': ["'self'", "'unsafe-inline'"],
'img-src': ["'self'", "data:", "https://*"],
'font-src': ["'self'", "https://fonts.gstatic.com"],
'connect-src': ["'self'"],
}
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.middleware.csp.ContentSecurityPolicyMiddleware', # 新增CSP中间件
# ... 其他中间件
]
# 或者使用常量配置
from django.middleware.csp import CSP_SELF, CSP_UNSAFE_INLINE
CSP_CONFIG = {
'default-src': [CSP_SELF],
'script-src': [CSP_SELF, CSP_UNSAFE_INLINE, "https://cdn.example.com"],
}
{# templates/blog/components/article_card.html #}
{% partialdef article_card article %}
<div class="card article-card mb-3">
<div class="card-body">
<h5 class="card-title">{{ article.title }}</h5>
<p class="card-text">{{ article.content|truncatewords:30 }}</p>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">
作者:{{ article.author.username }} |
发布时间:{{ article.published_at|date:"Y-m-d" }}
</small>
<a href="{% url 'article_detail' article.id %}"class="btn btn-sm btn-primary">
阅读全文
</a>
</div>
</div>
</div>
{% endpartialdef %}
{# 在模板中使用 #}
{% load partials %}
{% for article in articles %}
{% partial article_card article=article %}
{% endfor %}
Django ORM是框架的核心优势,掌握其高级用法能极大提升开发效率:# advanced_queries.py
from django.db import models
from django.db.models import Q, F, Count, Sum, Avg, Max, Min, Subquery, OuterRef
from django.db.models.functions import TruncDate, TruncMonth, Concat
from django.contrib.postgres.aggregates import ArrayAgg
from django.utils import timezone
from datetime import timedelta
# 1. 复杂条件查询
defget_popular_articles(days=30):
"""获取过去30天内的热门文章"""
from_date = timezone.now() - timedelta(days=days)
return Article.objects.filter(
Q(status='published') &
Q(published_at__gte=from_date) &
(
Q(view_count__gt=1000) |
Q(comments__created_at__gte=from_date) # 近期有评论
)
).annotate(
comment_count=Count('comments'),
recent_comment_count=Count(
'comments',
filter=Q(comments__created_at__gte=from_date)
)
).order_by('-view_count', '-recent_comment_count')
# 2. 子查询和关联优化
defget_author_statistics():
"""获取作者统计数据"""
from blog.models import User
recent_articles = Article.objects.filter(
author=OuterRef('pk'),
status='published',
published_at__gte=timezone.now() - timedelta(days=90)
).order_by('-published_at')[:5]
return User.objects.annotate(
total_articles=Count('articles', filter=Q(articles__status='published')),
total_views=Sum('articles__view_count', filter=Q(articles__status='published')),
avg_rating=Avg('articles__comments__rating', filter=Q(articles__status='published')),
latest_articles=Subquery(
recent_articles.values('title')[:3]
)
).filter(
total_articles__gt=0
).order_by('-total_views')
# 3. 批量操作和性能优化
defoptimize_batch_operations():
"""批量操作示例"""
# 批量创建(避免N+1问题)
categories = [
Category(name='Python基础', description='Python基础语法和核心概念'),
Category(name='Web开发', description='Django、Flask等Web框架'),
Category(name='数据分析', description='Pandas、NumPy等数据分析库'),
Category(name='人工智能', description='机器学习、深度学习相关'),
]
created_categories = Category.objects.bulk_create(categories)
# 批量更新(使用F表达式避免竞态条件)
Article.objects.filter(
status='published',
published_at__lt=timezone.now() - timedelta(days=365)
).update(
status='archived',
updated_at=timezone.now()
)
# 使用select_related和prefetch_related优化关联查询
articles_with_optimized_relations = Article.objects.select_related(
'author', 'category'
).prefetch_related(
'comments', 'tags'
).filter(status='published')[:10]
return created_categories
需求背景:为技术社区搭建一个博客系统,支持文章发布、分类管理、评论互动、用户权限控制等功能。
# blog/models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils.text import slugify
from markdownx.models import MarkdownxField
from taggit.managers import TaggableManager
classBlogPost(models.Model):
"""博客文章模型"""
STATUS_CHOICES = [
('draft', '草稿'),
('review', '审核中'),
('published', '已发布'),
('archived', '已归档'),
]
title = models.CharField(max_length=200, verbose_name="标题")
slug = models.SlugField(max_length=250, unique=True, blank=True, verbose_name="URL标识")
content = MarkdownxField(verbose_name="内容")
excerpt = models.TextField(max_length=500, blank=True, verbose_name="摘要")
cover_image = models.ImageField(
upload_to='blog/covers/',
blank=True,
verbose_name="封面图片"
)
author = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name='blog_posts',
verbose_name="作者"
)
category = models.ForeignKey(
'Category',
on_delete=models.SET_NULL,
null=True,
related_name='posts',
verbose_name="分类"
)
tags = TaggableManager(blank=True, verbose_name="标签")
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='draft',
verbose_name="状态"
)
view_count = models.PositiveIntegerField(default=0, verbose_name="浏览量")
likes = models.ManyToManyField(
User,
related_name='liked_posts',
blank=True,
verbose_name="点赞用户"
)
published_at = models.DateTimeField(null=True, blank=True, verbose_name="发布时间")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
classMeta:
db_table = 'blog_posts'
verbose_name = '博客文章'
verbose_name_plural = '博客文章'
ordering = ['-published_at', '-created_at']
indexes = [
models.Index(fields=['status', 'published_at']),
models.Index(fields=['category', 'published_at']),
models.Index(fields=['slug']),
]
permissions = [
('can_publish', '可以发布文章'),
('can_review', '可以审核文章'),
('can_archive', '可以归档文章'),
]
def__str__(self):
return self.title
defsave(self, *args, **kwargs):
"""自动生成slug"""
ifnot self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
defget_absolute_url(self):
"""获取文章详情URL"""
return reverse('blog:post_detail', kwargs={'slug': self.slug})
defincrement_view_count(self):
"""增加浏览量"""
self.view_count = models.F('view_count') + 1
self.save(update_fields=['view_count'])
# blog/views.py
from django.views.generic import ListView, DetailView, CreateView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.urls import reverse_lazy
from django.shortcuts import get_object_or_404
from django.db.models import Count, Q
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from django.contrib.auth.decorators import login_required
from .models import BlogPost, Category
from .forms import BlogPostForm
classPostListView(ListView):
"""文章列表视图"""
model = BlogPost
template_name = 'blog/post_list.html'
context_object_name = 'posts'
paginate_by = 12
defget_queryset(self):
"""优化查询集"""
queryset = BlogPost.objects.filter(status='published')
# 按分类筛选
category_slug = self.kwargs.get('category_slug')
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
queryset = queryset.filter(category=category)
# 按标签筛选
tag = self.request.GET.get('tag')
if tag:
queryset = queryset.filter(tags__name=tag)
# 按搜索词筛选
search = self.request.GET.get('search')
if search:
queryset = queryset.filter(
Q(title__icontains=search) |
Q(content__icontains=search) |
Q(excerpt__icontains=search)
)
return queryset.select_related('author', 'category').prefetch_related('tags')
defget_context_data(self, **kwargs):
"""添加上下文数据"""
context = super().get_context_data(**kwargs)
# 热门文章
context['popular_posts'] = BlogPost.objects.filter(
status='published'
).order_by('-view_count')[:5]
# 分类统计
context['categories'] = Category.objects.annotate(
post_count=Count('posts', filter=Q(posts__status='published'))
).filter(post_count__gt=0)
return context
classPostDetailView(DetailView):
"""文章详情视图"""
model = BlogPost
template_name = 'blog/post_detail.html'
context_object_name = 'post'
defget_queryset(self):
"""只允许查看已发布的文章"""
return BlogPost.objects.filter(status='published')
defget_context_data(self, **kwargs):
"""添加上下文:相关文章、上一篇、下一篇"""
context = super().get_context_data(**kwargs)
post = self.get_object()
# 相关文章(同分类)
context['related_posts'] = BlogPost.objects.filter(
category=post.category,
status='published'
).exclude(id=post.id)[:6]
# 上一篇
context['prev_post'] = BlogPost.objects.filter(
status='published',
published_at__lt=post.published_at
).order_by('-published_at').first()
# 下一篇
context['next_post'] = BlogPost.objects.filter(
status='published',
published_at__gt=post.published_at
).order_by('published_at').first()
return context
defget(self, request, *args, **kwargs):
"""增加浏览量"""
response = super().get(request, *args, **kwargs)
self.object.increment_view_count()
return response
classPostCreateView(LoginRequiredMixin, CreateView):
"""创建文章视图"""
model = BlogPost
form_class = BlogPostForm
template_name = 'blog/post_form.html'
defform_valid(self, form):
"""自动设置作者"""
form.instance.author = self.request.user
return super().form_valid(form)
defget_success_url(self):
return reverse_lazy('blog:post_detail', kwargs={'slug': self.object.slug})
@login_required
@require_POST
deflike_post(request, slug):
"""点赞文章"""
post = get_object_or_404(BlogPost, slug=slug, status='published')
if request.user in post.likes.all():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
return JsonResponse({
'liked': liked,
'like_count': post.likes.count()
})
需求背景:搭建一个在线商城,支持商品管理、购物车、订单处理、支付集成、会员系统等功能。- 购物车和订单系统:Redis缓存购物车,事务处理订单
# shop/models.py
from django.db import models
from django.core.validators import MinValueValidator
from decimal import Decimal
classProduct(models.Model):
"""商品模型"""
name = models.CharField(max_length=200, verbose_name="商品名称")
sku = models.CharField(max_length=50, unique=True, verbose_name="商品编码")
description = models.TextField(verbose_name="商品描述")
price = models.DecimalField(
max_digits=10,
decimal_places=2,
validators=[MinValueValidator(Decimal('0.01'))],
verbose_name="价格"
)
stock = models.PositiveIntegerField(default=0, verbose_name="库存")
category = models.ForeignKey(
'Category',
on_delete=models.SET_NULL,
null=True,
related_name='products',
verbose_name="分类"
)
is_available = models.BooleanField(default=True, verbose_name="是否上架")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
classMeta:
db_table = 'shop_products'
verbose_name = '商品'
verbose_name_plural = '商品'
ordering = ['-created_at']
indexes = [
models.Index(fields=['sku']),
models.Index(fields=['category', 'is_available']),
]
def__str__(self):
return self.name
defdecrease_stock(self, quantity):
"""减少库存"""
if self.stock >= quantity:
self.stock -= quantity
self.save(update_fields=['stock'])
returnTrue
returnFalse
classOrder(models.Model):
"""订单模型"""
STATUS_CHOICES = [
('pending', '待支付'),
('paid', '已支付'),
('processing', '处理中'),
('shipped', '已发货'),
('delivered', '已送达'),
('cancelled', '已取消'),
('refunded', '已退款'),
]
order_number = models.CharField(max_length=50, unique=True, verbose_name="订单号")
user = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
related_name='orders',
verbose_name="用户"
)
total_amount = models.DecimalField(
max_digits=12,
decimal_places=2,
verbose_name="总金额"
)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='pending',
verbose_name="状态"
)
shipping_address = models.TextField(verbose_name="收货地址")
payment_method = models.CharField(max_length=50, verbose_name="支付方式")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
classMeta:
db_table = 'shop_orders'
verbose_name = '订单'
verbose_name_plural = '订单'
ordering = ['-created_at']
def__str__(self):
return self.order_number
defsave(self, *args, **kwargs):
"""自动生成订单号"""
ifnot self.order_number:
import uuid
self.order_number = f'ORD{str(uuid.uuid4().int)[:10]}'
super().save(*args, **kwargs)
问题描述:在模板中遍历对象及其关联对象时,Django会为每个关联对象单独查询数据库,导致大量数据库查询。解决方案:使用select_related和prefetch_related# 低效写法
defget_inefficient_posts():
posts = BlogPost.objects.filter(status='published')
# 模板中访问post.author.username会触发N+1查询
return posts
# 高效写法
defget_efficient_posts():
posts = BlogPost.objects.filter(status='published').select_related(
'author', 'category'
).prefetch_related(
'tags', 'comments'
)
return posts
# 复杂关联优化
defget_complex_queryset():
from django.db.models import Prefetch
return BlogPost.objects.filter(
status='published'
).select_related('author').prefetch_related(
Prefetch(
'comments',
queryset=Comment.objects.filter(
is_active=True
).select_related('user'),
to_attr='active_comments'
)
)
问题描述:默认Admin后台功能有限,需要根据业务需求进行深度定制。# admin.py
from django.contrib import admin
from django.utils.html import format_html
from django.urls import reverse
from .models import BlogPost, Category
classBlogPostAdmin(admin.ModelAdmin):
"""博客文章管理后台定制"""
list_display = ['title', 'author', 'category', 'status', 'view_count', 'published_at', 'actions']
list_filter = ['status', 'category', 'published_at']
search_fields = ['title', 'content', 'author__username']
readonly_fields = ['view_count', 'created_at', 'updated_at']
list_per_page = 20
date_hierarchy = 'published_at'
actions = ['make_published', 'make_archived']
fieldsets = [
('基本信息', {
'fields': ['title', 'slug', 'content', 'excerpt', 'cover_image']
}),
('分类和标签', {
'fields': ['category', 'tags']
}),
('状态和权限', {
'fields': ['status', 'author', 'published_at']
}),
('统计信息', {
'fields': ['view_count', 'created_at', 'updated_at'],
'classes': ['collapse']
}),
]
defactions(self, obj):
"""自定义操作列"""
links = []
if obj.status == 'draft':
links.append(format_html(
'<a href="{}" class="button">发布</a>',
reverse('admin:publish_post', args=[obj.pk])
))
return format_html(' '.join(links))
actions.short_description = '操作'
defmake_published(self, request, queryset):
"""批量发布文章"""
queryset.update(status='published', published_at=timezone.now())
self.message_user(request, f'{queryset.count()}篇文章已发布')
make_published.short_description = '发布选中的文章'
defmake_archived(self, request, queryset):
"""批量归档文章"""
queryset.update(status='archived')
self.message_user(request, f'{queryset.count()}篇文章已归档')
make_archived.short_description = '归档选中的文章'
defget_queryset(self, request):
"""根据权限过滤查询集"""
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
admin.site.register(BlogPost, BlogPostAdmin)
问题描述:需要为前端应用提供RESTful API接口。解决方案:使用Django REST Framework# api/serializers.py
from rest_framework import serializers
from blog.models import BlogPost, Comment
classUserSerializer(serializers.ModelSerializer):
"""用户序列化器"""
classMeta:
model = User
fields = ['id', 'username', 'email', 'date_joined']
read_only_fields = ['date_joined']
classCommentSerializer(serializers.ModelSerializer):
"""评论序列化器"""
user = UserSerializer(read_only=True)
classMeta:
model = Comment
fields = ['id', 'content', 'user', 'created_at']
read_only_fields = ['created_at']
classBlogPostSerializer(serializers.ModelSerializer):
"""博客文章序列化器"""
author = UserSerializer(read_only=True)
comments = CommentSerializer(many=True, read_only=True)
likes_count = serializers.IntegerField(source='likes.count', read_only=True)
classMeta:
model = BlogPost
fields = [
'id', 'title', 'slug', 'content', 'excerpt',
'author', 'category', 'status', 'view_count',
'likes_count', 'comments', 'published_at',
'created_at', 'updated_at'
]
read_only_fields = [
'slug', 'view_count', 'likes_count',
'published_at', 'created_at', 'updated_at'
]
defcreate(self, validated_data):
"""创建文章时自动设置作者"""
validated_data['author'] = self.context['request'].user
return super().create(validated_data)
# api/views.py
from rest_framework import viewsets, permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response
from blog.models import BlogPost
from .serializers import BlogPostSerializer
classBlogPostViewSet(viewsets.ModelViewSet):
"""博客文章视图集"""
queryset = BlogPost.objects.filter(status='published')
serializer_class = BlogPostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
lookup_field = 'slug'
defget_queryset(self):
"""根据用户权限返回查询集"""
queryset = super().get_queryset()
# 管理员可以查看所有文章
if self.request.user.is_staff:
return BlogPost.objects.all()
# 作者可以查看自己的所有文章
if self.request.user.is_authenticated:
return queryset.filter(author=self.request.user)
# 匿名用户只能查看已发布的文章
return queryset
@action(detail=True, methods=['post'])
deflike(self, request, slug=None):
"""点赞文章"""
post = self.get_object()
if request.user in post.likes.all():
post.likes.remove(request.user)
liked = False
else:
post.likes.add(request.user)
liked = True
return Response({
'liked': liked,
'likes_count': post.likes.count()
})
@action(detail=True, methods=['post'])
defpublish(self, request, slug=None):
"""发布文章"""
post = self.get_object()
# 权限检查
if post.author != request.user andnot request.user.is_staff:
return Response(
{'error': '无权操作'},
status=status.HTTP_403_FORBIDDEN
)
post.status = 'published'
post.published_at = timezone.now()
post.save()
return Response({'status': 'published'})
- 数据库:PostgreSQL + PgBouncer连接池
- 监控告警:Prometheus + Grafana
# settings/production.py
import os
from .base import *
# 安全设置
DEBUG = False
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ.get('DB_NAME', 'django_app'),
'USER': os.environ.get('DB_USER', 'django_user'),
'PASSWORD': os.environ.get('DB_PASSWORD', ''),
'HOST': os.environ.get('DB_HOST', 'localhost'),
'PORT': os.environ.get('DB_PORT', '5432'),
'CONN_MAX_AGE': 600, # 连接池超时时间
'OPTIONS': {
'connect_timeout': 10,
'application_name': 'django_app',
},
}
}
# 缓存配置
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': f"redis://{os.environ.get('REDIS_HOST', 'localhost')}:6379/1",
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'PASSWORD': os.environ.get('REDIS_PASSWORD', None),
'SOCKET_CONNECT_TIMEOUT': 5,
'SOCKET_TIMEOUT': 5,
},
'KEY_PREFIX': 'django_app',
}
}
# 静态文件配置
STATIC_ROOT = '/var/www/static/'
STATIC_URL = '/static/'
MEDIA_ROOT = '/var/www/media/'
MEDIA_URL = '/media/'
# 文件存储(使用S3)
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_S3_REGION_NAME = os.environ.get('AWS_S3_REGION_NAME', 'us-east-1')
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
AWS_DEFAULT_ACL = 'public-read'
AWS_QUERYSTRING_AUTH = False
# 日志配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
'simple': {
'format': '{levelname} {message}',
'style': '{',
},
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'formatter': 'simple',
},
'file': {
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/django/app.log',
'maxBytes': 1024 * 1024 * 10, # 10MB
'backupCount': 10,
'formatter': 'verbose',
},
'error_file': {
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/var/log/django/error.log',
'maxBytes': 1024 * 1024 * 10,
'backupCount': 10,
'formatter': 'verbose',
'level': 'ERROR',
},
},
'loggers': {
'django': {
'handlers': ['console', 'file', 'error_file'],
'level': os.environ.get('DJANGO_LOG_LEVEL', 'INFO'),
'propagate': True,
},
'blog': {
'handlers': ['console', 'file', 'error_file'],
'level': 'INFO',
'propagate': False,
},
},
}
# 1. 索引优化
classBlogPost(models.Model):
# ... 其他字段
classMeta:
indexes = [
# 复合索引优化常见查询
models.Index(fields=['status', 'published_at']),
models.Index(fields=['category', 'published_at']),
# 全文搜索索引
GinIndex(fields=['title'], name='title_gin_idx'),
]
# 2. 查询优化
defoptimized_queries():
# 使用values/values_list减少数据传输
popular_titles = BlogPost.objects.filter(
view_count__gt=1000
).values_list('title', flat=True)[:10]
# 使用only/defer延迟加载字段
articles = BlogPost.objects.only(
'title', 'author_id', 'published_at'
).filter(status='published')[:20]
# 使用iterator处理大数据集
for article in BlogPost.objects.iterator(chunk_size=1000):
process_article(article)
return popular_titles
# 视图缓存
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) # 缓存15分钟
defarticle_list(request):
# ...
# 模板片段缓存
{% load cache %}
{% cache 300 article_detail article.id %}
{# 文章详情内容,缓存5分钟 #}
{% endcache %}
# 低级缓存API
from django.core.cache import cache
defget_popular_articles():
"""获取热门文章,使用缓存"""
cache_key = 'popular_articles'
articles = cache.get(cache_key)
ifnot articles:
articles = BlogPost.objects.filter(
status='published'
).order_by('-view_count')[:10]
# 缓存1小时
cache.set(cache_key, articles, 60 * 60)
return articles
- Django定位:全功能企业级Web框架,内置ORM、Admin后台、用户认证等核心功能
- MTV架构:Model(数据层)、Template(展示层)、View(业务逻辑层)三层分离
- 核心优势:开箱即用、安全性高、扩展性强、文档完善、社区活跃
- 适用场景:内容管理系统、企业级应用、电子商务平台、社交网络应用
- 最新特性:Django 6.0引入内置后台任务框架、原生CSP支持、模板局部文件功能
- 性能优化:使用select_related、prefetch_related优化关联查询,合理使用缓存
- 生产部署:Gunicorn + Nginx + PostgreSQL + Redis的完整架构方案
- 《Django企业开发实战》 - 作者:胡阳,全面讲解Django在企业级项目中的应用
- 《Django By Example》 - 作者:Antonio Mele,通过完整项目学习Django
- 《Two Scoops of Django》 - 作者:Daniel Roy Greenfeld,Django最佳实践指南
- 官方文档:https://docs.djangoproject.com/,最权威的Django学习资料
- Django Girls教程:https://tutorial.djangogirls.org/,适合初学者入门
- Real Python Django教程:https://realpython.com/tutorials/django/,实战导向的教程
- Django CMS:https://github.com/django-cms/django-cms,学习复杂CMS系统设计
- Saleor:https://github.com/saleor/saleor,学习电子商务平台架构
- Cookiecutter Django:https://github.com/cookiecutter/cookiecutter-django,学习生产级项目配置
- Django REST Framework:深入掌握API开发,构建现代化前后端分离应用
- Django Channels:学习WebSocket实时通信,构建聊天室、通知系统等实时应用
- Django + Celery:掌握异步任务处理,构建定时任务、批量处理等后台服务
- Django性能调优:学习数据库优化、缓存策略、异步处理等高级技巧
下一篇文章我们将深入解析Python LangChain模块:AI应用开发框架,构建智能代理系统。你将学会:- 如何集成大模型(OpenAI、Hugging Face)到你的应用中
- 构建检索增强生成(RAG)系统,让AI基于你的知识库回答问题
LangChain正在彻底改变AI应用开发的方式,无论你是想构建智能客服、文档分析助手,还是代码生成工具,LangChain都能为你提供强大的支持。敬请期待!
关于我们:Python与AI智能研习社致力于分享最实用的Python技术和AI应用开发经验。如果你觉得这篇文章有帮助,欢迎分享给更多开发者!问题交流:在使用Django过程中遇到问题?欢迎在评论区留言,我们会尽力解答!下一篇预告:《Python LangChain模块深度解析:AI应用开发框架,构建智能代理系统》