1. 项目概述
这个基于Django框架开发的日用品商场系统,是我为一个本地连锁超市集团设计的B2C电商解决方案。系统上线后成功支撑了日均3000+订单的业务量,将原本线下的日用品销售业务完整迁移到了线上平台。
作为全栈开发者,我在这个项目中负责从需求分析到部署上线的全流程开发。系统采用经典的MTV架构模式,前端使用Bootstrap+jQuery实现响应式布局,后端基于Django 3.2 LTS版本开发,数据库选用MySQL 8.0作为主存储,Redis作缓存层。
2. 核心需求解析
2.1 业务需求分析
在与超市管理团队深入沟通后,我们梳理出以下核心业务需求:
- 商品管理:需要支持2000+SKU的分类管理,包含日用品特有的属性如保质期、规格参数等
- 会员体系:实现积分累积、等级折扣等促销功能
- 订单处理:支持线下自提和快递配送两种模式
- 库存同步:与现有ERP系统实时同步库存数据
- 营销工具:优惠券、限时折扣等促销功能
2.2 技术需求拆解
基于业务需求,我们确定了以下技术实现要点:
- 高并发商品页:采用Redis缓存商品详情,QPS达到500+
- 实时库存检查:通过Django Channels实现WebSocket库存预警
- 搜索优化:使用Django Haystack+Elasticsearch实现商品搜索
- 支付对接:集成微信支付和支付宝SDK
- 报表系统:基于Pandas生成销售数据分析报表
3. 系统架构设计
3.1 技术栈选型
经过技术评估,最终确定的技术栈如下:
| 层级 | 技术选型 | 选型理由 |
|---|---|---|
| 前端 | Bootstrap5+jQuery | 快速实现响应式布局,兼容移动端 |
| 后端 | Django 3.2 + Django REST framework | 完善的Admin系统,适合快速开发电商后台 |
| 数据库 | MySQL 8.0 | 事务支持完善,适合订单系统 |
| 缓存 | Redis 6.0 | 高性能缓存,支撑秒杀活动 |
| 搜索 | Elasticsearch 7.0 | 商品搜索性能优化 |
| 异步任务 | Celery + RabbitMQ | 处理订单异步任务 |
3.2 数据库设计
核心数据表关系如下:
python复制class Product(models.Model):
name = models.CharField(max_length=200)
category = models.ForeignKey('Category', on_delete=models.PROTECT)
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.IntegerField(default=0)
expiry_date = models.DateField() # 日用品特有的保质期字段
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(max_length=20, choices=ORDER_STATUS)
payment_method = models.CharField(max_length=50)
total_amount = models.DecimalField(max_digits=12, decimal_places=2)
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.PROTECT)
quantity = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
4. 核心功能实现
4.1 商品展示系统
商品列表页采用分页缓存策略,显著提升加载速度:
python复制from django.core.cache import cache
def product_list(request):
page = request.GET.get('page', 1)
cache_key = f'products_page_{page}'
products = cache.get(cache_key)
if not products:
products = Product.objects.filter(is_active=True).select_related('category')
paginator = Paginator(products, 20)
products = paginator.page(page)
cache.set(cache_key, products, timeout=60*15) # 缓存15分钟
return render(request, 'shop/product_list.html', {'products': products})
4.2 购物车实现
使用Django session实现购物车功能,关键代码如下:
python复制def add_to_cart(request):
product_id = request.POST.get('product_id')
quantity = int(request.POST.get('quantity', 1))
cart = request.session.get('cart', {})
cart[product_id] = cart.get(product_id, 0) + quantity
request.session['cart'] = cart
return JsonResponse({'status': 'success', 'cart_items': len(cart)})
4.3 订单处理流程
订单创建包含完整的业务逻辑校验:
python复制@transaction.atomic
def create_order(request):
cart = request.session.get('cart', {})
if not cart:
return HttpResponseBadRequest("购物车为空")
try:
with transaction.atomic():
order = Order.objects.create(
user=request.user,
status='pending',
total_amount=0
)
total = 0
for product_id, quantity in cart.items():
product = Product.objects.select_for_update().get(pk=product_id)
if product.stock < quantity:
raise ValueError(f"{product.name}库存不足")
OrderItem.objects.create(
order=order,
product=product,
quantity=quantity,
price=product.price
)
product.stock -= quantity
product.save()
total += product.price * quantity
order.total_amount = total
order.save()
del request.session['cart']
# 异步任务:发送订单确认邮件
send_order_confirmation.delay(order.id)
return redirect('order_detail', order_id=order.id)
except Exception as e:
return HttpResponseBadRequest(str(e))
5. 性能优化实践
5.1 数据库查询优化
针对商品列表N+1查询问题,我们采用以下优化措施:
- 使用
select_related和prefetch_related减少查询次数 - 添加适当的数据库索引
- 对复杂查询使用annotate和aggregate
python复制# 优化后的查询示例
products = Product.objects.filter(
is_active=True
).select_related(
'category'
).prefetch_related(
'images'
).annotate(
discount_price=F('price') * 0.9
).only(
'name', 'price', 'category__name'
)
5.2 缓存策略设计
系统采用多级缓存策略:
- 全页缓存:首页和商品分类页使用整页缓存
- 片段缓存:商品推荐部分使用模板片段缓存
- 数据缓存:频繁访问的数据如商品详情使用Redis缓存
缓存失效策略:
- 商品修改时清除相关缓存
- 定时任务每晚清除所有缓存
- 促销活动期间缩短缓存时间
6. 安全防护措施
6.1 常见Web安全防护
- CSRF防护:启用Django内置的CSRF中间件
- XSS防护:模板自动转义,富文本内容使用bleach清洗
- SQL注入:使用ORM或参数化查询
- 敏感数据:密码使用PBKDF2算法加密存储
6.2 订单安全设计
针对电商特有的安全问题,我们实现了:
python复制class OrderPermission(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# 确保用户只能访问自己的订单
return obj.user == request.user
支付回调接口增加了签名验证:
python复制def verify_alipay_signature(params):
sign = params.pop('sign')
sign_type = params.pop('sign_type')
params_str = '&'.join([f'{k}={v}' for k,v in sorted(params.items())])
public_key = settings.ALIPAY_PUBLIC_KEY
# 使用RSA验证签名
return rsa.verify(params_str.encode(), sign, public_key)
7. 部署架构
7.1 生产环境配置
采用Docker-compose部署方案:
yaml复制version: '3'
services:
web:
build: .
command: gunicorn ecommerce.wsgi:application --bind 0.0.0.0:8000
volumes:
- static_data:/app/static
depends_on:
- redis
- db
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_DATABASE: ecommerce
redis:
image: redis:6.0
celery:
build: .
command: celery -A ecommerce worker -l info
depends_on:
- redis
- db
volumes:
static_data:
7.2 监控方案
- 应用监控:Sentry收集错误日志
- 性能监控:Prometheus+Grafana监控系统指标
- 业务监控:自定义仪表盘显示关键业务指标
8. 开发经验总结
在项目开发过程中,有几个关键经验值得分享:
- 日用品特殊属性处理:
- 保质期商品需要提前30天预警
- 不同规格商品(如大包装vs小包装)需要特殊的价格计算逻辑
- 易碎品需要在订单中标注特殊包装要求
- 促销活动实现技巧:
python复制def apply_promotions(cart):
# 周三会员日折扣
if datetime.now().weekday() == 2: # 周三
for item in cart.items.all():
if item.product.category.name == '清洁用品':
item.discount = 0.8 # 8折
# 满减活动
total = cart.total_amount()
if total > 100:
cart.discount_amount = 20
cart.save()
- 库存同步痛点:
- 与ERP系统同步时增加乐观锁机制
- 设置合理的库存缓存时间(我们最终确定为5分钟)
- 重要促销活动前手动刷新库存
这个日用品商城系统从开发到上线历时4个月,期间遇到了许多业务逻辑上的挑战,特别是日用品行业特有的保质期管理和规格转换问题。通过这个项目,我深刻体会到电商系统开发中业务理解的重要性,技术实现必须服务于具体的业务场景。