1. 项目概述
作为一名从事Web开发多年的程序员,我一直对音乐教育领域充满兴趣。去年在指导一位学生的毕业设计时,我们共同开发了一个基于Django的乐器销售与教学平台。这个项目将电子商务与在线教育相结合,为乐器爱好者提供了一站式的购物和学习体验。
这个平台最吸引我的地方在于它解决了乐器学习者的两个核心痛点:一是购买乐器后缺乏系统的学习资源,二是传统乐器教学受限于时间和空间。通过将商品销售与教学视频整合在一个平台,用户可以在购买乐器的同时获得配套的学习资源,大大提升了用户体验。
在技术选型上,我们选择了Django框架作为后端基础,主要考虑到以下几点:
- Django自带强大的ORM系统,能快速构建数据模型
- 内置的管理后台可以极大减少开发工作量
- 完善的认证系统和安全机制
- 活跃的社区和丰富的第三方库支持
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术栈选择
整个项目采用经典的MVC架构,具体技术栈如下:
前端技术:
- HTML5 + CSS3 + JavaScript
- Bootstrap 5响应式框架
- jQuery简化DOM操作
- Video.js视频播放组件
后端技术:
- Python 3.8
- Django 3.2
- Django REST framework(用于API开发)
- Django-allauth(用户认证)
- Django-crispy-forms(表单渲染)
数据库:
- MySQL 8.0(生产环境)
- SQLite(开发环境)
开发工具:
- PyCharm Professional
- Git版本控制
- Postman API测试
2.2 系统模块划分
系统主要分为两大模块:
-
用户端功能模块
- 用户认证(注册/登录/找回密码)
- 商品浏览与搜索
- 购物车与订单管理
- 教学视频观看与互动
- 个人中心管理
-
管理员端功能模块
- 用户管理
- 商品管理
- 订单管理
- 视频内容管理
- 系统配置
2.3 数据库设计
我们采用了关系型数据库设计,主要包含以下核心表:
-
用户相关表
- User(用户基础信息)
- UserProfile(用户扩展信息)
- Address(收货地址)
-
商品相关表
- Product(商品信息)
- ProductCategory(商品分类)
- ProductImage(商品图片)
-
订单相关表
- Order(订单主表)
- OrderItem(订单明细)
- Payment(支付记录)
-
教学相关表
- VideoCourse(视频课程)
- VideoChapter(视频章节)
- UserProgress(学习进度)
-
系统相关表
- SystemConfig(系统配置)
- Banner(轮播图)
- Notification(通知公告)
提示:在实际开发中,我们使用了Django的ORM系统,通过定义Model类来创建这些表结构,大大简化了数据库操作。
3. 核心功能实现
3.1 用户认证系统
用户认证是平台的基础功能,我们基于Django-allauth实现了完整的认证流程:
python复制# accounts/views.py
from allauth.account.views import LoginView, SignupView
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
class CustomLoginView(LoginView):
template_name = 'accounts/login.html'
def form_valid(self, form):
# 添加自定义登录逻辑
remember = self.request.POST.get('remember')
if remember:
self.request.session.set_expiry(30*24*60*60) # 记住我30天
return super().form_valid(form)
class CustomSignupView(SignupView):
template_name = 'accounts/register.html'
def form_valid(self, form):
# 添加自定义注册逻辑
response = super().form_valid(form)
# 发送欢迎邮件
send_welcome_email(self.request, self.user)
return response
@login_required
def profile(request):
return render(request, 'accounts/profile.html')
关键实现细节:
- 使用Django-allauth提供的模板标签快速构建表单
- 自定义表单验证逻辑
- 实现"记住我"功能
- 注册成功后自动发送欢迎邮件
- 集成短信验证码功能(使用阿里云短信服务)
3.2 商品展示与搜索
商品模块实现了以下功能:
- 商品分类展示
- 多条件筛选
- 关键词搜索
- 商品详情页
- 收藏功能
python复制# products/views.py
from django.db.models import Q
from django.views.generic import ListView, DetailView
from .models import Product, ProductCategory
class ProductListView(ListView):
model = Product
template_name = 'products/list.html'
paginate_by = 12
def get_queryset(self):
queryset = super().get_queryset()
# 分类筛选
category_id = self.request.GET.get('category')
if category_id:
queryset = queryset.filter(category_id=category_id)
# 价格区间
min_price = self.request.GET.get('min_price')
max_price = self.request.GET.get('max_price')
if min_price and max_price:
queryset = queryset.filter(
price__gte=min_price,
price__lte=max_price
)
# 关键词搜索
keyword = self.request.GET.get('q')
if keyword:
queryset = queryset.filter(
Q(name__icontains=keyword) |
Q(description__icontains=keyword)
)
return queryset.order_by('-created_at')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['categories'] = ProductCategory.objects.all()
return context
class ProductDetailView(DetailView):
model = Product
template_name = 'products/detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['related_products'] = Product.objects.filter(
category=self.object.category
).exclude(pk=self.object.pk)[:4]
return context
性能优化点:
- 使用select_related/prefetch_related减少数据库查询
- 实现分页功能避免加载过多数据
- 对商品图片使用懒加载
- 使用Django缓存框架缓存热门商品
3.3 购物车与订单系统
购物车和订单是电商平台的核心功能,我们实现了完整的购物流程:
python复制# orders/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, CreateView
from django.shortcuts import redirect
from .models import Cart, Order, OrderItem
from .forms import CheckoutForm
class CartView(LoginRequiredMixin, ListView):
model = Cart
template_name = 'orders/cart.html'
def get_queryset(self):
return Cart.objects.filter(user=self.request.user)
def post(self, request):
# 处理购物车更新
cart_items = request.POST.getlist('cart_items')
quantities = request.POST.getlist('quantities')
# 更新购物车商品数量
for item_id, quantity in zip(cart_items, quantities):
cart_item = Cart.objects.get(pk=item_id)
cart_item.quantity = quantity
cart_item.save()
return redirect('checkout')
class CheckoutView(LoginRequiredMixin, CreateView):
form_class = CheckoutForm
template_name = 'orders/checkout.html'
def form_valid(self, form):
order = form.save(commit=False)
order.user = self.request.user
order.save()
# 从购物车创建订单项
cart_items = Cart.objects.filter(user=self.request.user)
for item in cart_items:
OrderItem.objects.create(
order=order,
product=item.product,
quantity=item.quantity,
price=item.product.price
)
item.delete() # 清空购物车
# 处理支付
process_payment(order)
return redirect('order_detail', pk=order.pk)
订单状态机设计:
mermaid复制stateDiagram
[*] --> Pending
Pending --> Paid: 支付成功
Pending --> Cancelled: 取消订单
Paid --> Shipped: 发货
Shipped --> Delivered: 确认收货
Shipped --> ReturnRequested: 申请退货
ReturnRequested --> Returned: 退货完成
ReturnRequested --> Rejected: 拒绝退货
3.4 教学视频系统
教学视频模块实现了以下功能:
- 视频分类浏览
- 视频播放与进度记录
- 评论与互动
- 学习进度跟踪
python复制# education/views.py
from django.views.generic import DetailView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import VideoCourse, UserProgress
class VideoDetailView(LoginRequiredMixin, DetailView):
model = VideoCourse
template_name = 'education/video_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# 获取或创建学习进度记录
progress, created = UserProgress.objects.get_or_create(
user=self.request.user,
video=self.object
)
context['progress'] = progress
return context
def post(self, request, *args, **kwargs):
# 更新学习进度
video = self.get_object()
current_time = request.POST.get('current_time')
duration = request.POST.get('duration')
progress, _ = UserProgress.objects.get_or_create(
user=request.user,
video=video
)
progress.current_time = current_time
progress.duration = duration
if float(current_time) / float(duration) > 0.9:
progress.is_completed = True
progress.save()
return JsonResponse({'status': 'success'})
视频播放实现要点:
- 使用Video.js作为播放器前端
- 实现断点续播功能
- 视频文件存储在阿里云OSS
- 使用HLS协议实现自适应码率
- 添加水印保护版权
4. 系统部署与优化
4.1 生产环境部署
我们使用以下技术栈进行生产环境部署:
服务器配置:
- 阿里云ECS(2核4G)
- Ubuntu 20.04 LTS
- Nginx作为反向代理
- Gunicorn作为应用服务器
- MySQL 8.0数据库
- Redis缓存
部署步骤:
- 安装系统依赖:
bash复制sudo apt update
sudo apt install -y python3-pip python3-dev libmysqlclient-dev nginx
- 配置虚拟环境:
bash复制python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
- 配置Gunicorn服务:
ini复制[Unit]
Description=Gunicorn service
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/music-platform
ExecStart=/home/ubuntu/music-platform/venv/bin/gunicorn --access-logfile - --workers 3 --bind unix:/run/gunicorn.sock core.wsgi:application
[Install]
WantedBy=multi-user.target
- 配置Nginx:
nginx复制server {
listen 80;
server_name example.com;
location / {
include proxy_params;
proxy_pass http://unix:/run/gunicorn.sock;
}
location /static/ {
alias /home/ubuntu/music-platform/static/;
}
location /media/ {
alias /home/ubuntu/music-platform/media/;
}
}
4.2 性能优化
-
数据库优化:
- 为常用查询字段添加索引
- 使用select_related和prefetch_related减少查询次数
- 配置数据库连接池
-
缓存策略:
- 使用Redis缓存热门商品和页面片段
- 实现整页缓存对静态内容
- 配置Django缓存框架:
python复制CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379/1', 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', } } } -
前端优化:
- 使用Webpack打包静态资源
- 实现懒加载图片和组件
- 启用Gzip压缩
- 配置CDN加速静态资源
-
异步任务:
- 使用Celery处理耗时任务(如发送邮件、生成报表)
- 配置任务队列:
python复制CELERY_BROKER_URL = 'redis://localhost:6379/0' CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
5. 开发经验与教训
在开发这个平台的过程中,我们积累了一些宝贵的经验:
5.1 技术选型心得
-
Django vs Flask:
- Django更适合这种包含管理后台的复杂应用
- 自带的功能(如认证、ORM、Admin)节省了大量开发时间
- 但灵活性不如Flask,某些定制功能需要绕道实现
-
数据库选择:
- 开发阶段使用SQLite确实方便
- 但生产环境切换MySQL时遇到了一些兼容性问题
- 建议从一开始就使用与生产环境相同的数据库
-
前端框架:
- 简单项目可以不使用Vue/React
- 但复杂交互多的页面,jQuery维护成本高
- 下次会考虑使用Django REST + 前端框架的架构
5.2 常见问题与解决方案
问题1:视频上传速度慢
- 原因:直接上传到应用服务器再转存OSS
- 解决方案:实现前端直传OSS,使用STS临时授权
问题2:订单超卖
- 原因:高并发下库存检查与扣减不同步
- 解决方案:使用select_for_update行锁
python复制with transaction.atomic():
product = Product.objects.select_for_update().get(pk=product_id)
if product.stock >= quantity:
product.stock -= quantity
product.save()
# 创建订单...
问题3:搜索性能差
- 原因:LIKE查询效率低
- 解决方案:引入Elasticsearch实现全文检索
- 实现:
python复制from elasticsearch_dsl import Document, Text, Integer
class ProductDocument(Document):
name = Text()
description = Text()
price = Integer()
class Index:
name = 'products'
5.3 项目改进方向
-
移动端体验优化
- 开发微信小程序版本
- 实现PWA支持离线访问
- 优化移动端支付流程
-
教学系统增强
- 添加直播教学功能
- 实现AI辅助练习评估
- 开发配套移动端APP
-
社交功能扩展
- 添加用户社区
- 实现乐器二手交易
- 举办在线音乐比赛
6. 源码解析
项目采用标准的Django项目结构:
code复制music_platform/
├── core/ # 项目主配置
├── accounts/ # 用户认证
├── products/ # 商品管理
├── orders/ # 订单系统
├── education/ # 教学系统
├── static/ # 静态文件
├── templates/ # 模板文件
├── manage.py
└── requirements.txt
核心Model示例:
python复制# products/models.py
from django.db import models
from django.utils.text import slugify
class ProductCategory(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='categories/', null=True)
class Meta:
verbose_name_plural = 'Product Categories'
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
def __str__(self):
return self.name
class Product(models.Model):
category = models.ForeignKey(
ProductCategory,
related_name='products',
on_delete=models.CASCADE
)
name = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField(default=0)
available = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['slug']),
models.Index(fields=['name']),
models.Index(fields=['price']),
]
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
def __str__(self):
return self.name
视图逻辑示例:
python复制# orders/api/views.py
from rest_framework import generics, permissions
from rest_framework.response import Response
from .models import Order
from .serializers import OrderSerializer
class OrderListCreateAPIView(generics.ListCreateAPIView):
serializer_class = OrderSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Order.objects.filter(user=self.request.user)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
class OrderRetrieveAPIView(generics.RetrieveAPIView):
serializer_class = OrderSerializer
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self):
return Order.objects.filter(user=self.request.user)
7. 项目总结
这个乐器销售与教学平台项目让我深刻体会到Django框架在快速开发复杂Web应用方面的优势。通过这个项目,我们实现了:
- 完整的电商功能(商品展示、购物车、订单、支付)
- 丰富的教学系统(视频播放、进度跟踪、互动评论)
- 健壮的后台管理系统
- 良好的用户体验和响应式设计
技术上的关键收获:
- Django ORM的高效使用
- 前后端分离的适度应用
- 性能优化实践经验
- 第三方服务集成(支付、短信、OSS)
如果重新开发这个项目,我会在以下方面改进:
- 采用更现代化的前端架构(如Vue.js)
- 实现更完善的微服务架构
- 加强自动化测试覆盖
- 优化CI/CD流程
这个项目已经稳定运行半年多,服务了数千名乐器爱好者。看到用户既能购买到心仪的乐器,又能通过我们的平台学习提升,这种成就感是单纯技术挑战无法比拟的。这也让我更加坚定了用技术解决实际问题的信念。
