1. 项目概述:Django在线购物平台开发全流程
这个基于Django框架的在线购物平台项目源码(14100行)是我在实际电商项目开发中提炼出的实战案例。不同于简单的教学Demo,它完整实现了电商平台的核心功能模块,包括用户认证、商品管理、订单处理、支付集成等企业级功能。我在开发过程中踩过不少坑,也积累了许多Django框架的高效使用技巧,这些都会在本文中详细分享。
Django作为Python生态中最成熟的Web框架之一,其"开箱即用"的特性特别适合快速构建功能完备的电商系统。这个项目采用了Django 3.2 LTS版本,数据库使用PostgreSQL,前端基于Bootstrap 5实现响应式布局。整个项目遵循Django的最佳实践模式,包括合理的app划分、自定义模型管理器、基于类的视图(CBV)等现代Django开发方式。
提示:虽然项目源码有14100行,但核心业务逻辑其实非常清晰。我会重点讲解那些在官方文档中不会提及,但在实际开发中至关重要的实现细节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 项目架构设计与技术选型
2.1 后端技术栈解析
项目采用经典的MTV(Model-Template-View)架构,这是Django对MVC模式的独特实现。我在技术选型时主要考虑了以下几个因素:
-
Django ORM:相比直接使用SQL,Django ORM提供了更高级的数据操作接口。例如在处理商品库存时,我使用了
select_for_update()来实现行级锁,防止超卖:python复制from django.db import transaction @transaction.atomic def reduce_stock(product_id, quantity): product = Product.objects.select_for_update().get(id=product_id) if product.stock >= quantity: product.stock -= quantity product.save() -
缓存策略:使用Redis作为缓存后端,对商品详情页实现了两级缓存:
- 整页缓存(15分钟)
- 热点数据缓存(商品基础信息,1小时)
配置示例:
python复制CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': 'redis://127.0.0.1:6379/1', 'OPTIONS': { 'CLIENT_CLASS': 'django_redis.client.DefaultClient', } } } -
异步任务:使用Celery处理耗时操作,如发送订单确认邮件、生成PDF发票等。这里有个关键点是要正确配置Celery的beat_schedule:
python复制app.conf.beat_schedule = { 'check-order-status-every-30-minutes': { 'task': 'orders.tasks.check_pending_orders', 'schedule': crontab(minute='*/30'), }, }
2.2 前端技术方案
前端部分没有采用流行的Vue/React,而是坚持使用Django模板引擎+Bootstrap的组合,主要基于以下考虑:
- 开发效率:对于中小型电商项目,SPA可能过度设计
- SEO友好:服务端渲染更利于搜索引擎抓取
- 维护成本:技术栈统一降低团队学习成本
我特别优化了静态资源的管理方式:
python复制STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
# 生产环境配置示例
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
3. 核心功能模块实现细节
3.1 用户认证系统增强
Django自带的auth模块虽然完善,但电商平台通常需要额外功能。我通过继承AbstractUser实现了扩展:
python复制from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
phone = models.CharField(max_length=20, blank=True)
avatar = models.ImageField(upload_to='avatars/', blank=True)
credit_score = models.IntegerField(default=100)
def get_full_address(self):
return f"{self.profile.province}{self.profile.city}{self.profile.district}"
认证流程中特别注意了以下几点:
- 登录限流:使用
django-ratelimit防止暴力破解 - 密码安全:强制要求8位以上且包含特殊字符
- 会话管理:设置合理的SESSION_COOKIE_AGE(默认2周)
3.2 商品模块设计
商品系统采用了EAV(实体-属性-值)模型来应对多变的商品属性需求:
python复制class Product(models.Model):
name = models.CharField(max_length=200)
base_price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.ForeignKey('Category', on_delete=models.PROTECT)
is_available = models.BooleanField(default=True)
@property
def current_price(self):
# 计算促销价等逻辑
return self.base_price
class ProductAttribute(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
attribute = models.ForeignKey('Attribute', on_delete=models.CASCADE)
value = models.CharField(max_length=500)
class Attribute(models.Model):
name = models.CharField(max_length=100)
is_filterable = models.BooleanField(default=False)
商品搜索使用Django的PostgreSQL特定功能:
python复制from django.contrib.postgres.search import SearchVector
def product_search(query):
return Product.objects.annotate(
search=SearchVector('name', 'description')
).filter(search=query)
3.3 购物车与订单系统
购物车设计考虑了游客状态和登录状态的兼容:
python复制class Cart:
def __init__(self, request):
self.session = request.session
cart = self.session.get('cart', {})
if not cart:
cart = self.session['cart'] = {}
self.cart = cart
def add(self, product_id, quantity=1):
product_id = str(product_id)
if product_id not in self.cart:
self.cart[product_id] = {'quantity': 0}
self.cart[product_id]['quantity'] += quantity
self.save()
def save(self):
self.session.modified = True
订单状态机是实现中最复杂的部分之一,我使用了状态模式:
python复制class OrderStatus:
def __init__(self, order):
self.order = order
def process(self):
raise NotImplementedError()
def cancel(self):
raise NotImplementedError()
class PendingStatus(OrderStatus):
def process(self):
if self.order.payment_confirmed:
self.order.status = 'processing'
return True
return False
def cancel(self):
self.order.status = 'cancelled'
return True
4. 性能优化与安全实践
4.1 数据库查询优化
-
select_related/prefetch_related:解决N+1查询问题
python复制# 错误方式:会产生N+1查询 orders = Order.objects.all() for order in orders: print(order.user.username) # 正确方式 orders = Order.objects.select_related('user').all() -
批量操作:使用bulk_create和update替代循环
python复制Product.objects.filter(category=1).update(price=F('price')*0.9) -
索引优化:为高频查询字段添加db_index
python复制class Order(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True) created_at = models.DateTimeField(auto_now_add=True, db_index=True)
4.2 安全防护措施
- XSS防护:Django模板自动转义,但要注意
mark_safe的使用 - CSRF防护:确保所有POST请求包含
{% csrf_token %} - SQL注入:永远使用ORM或参数化查询
- 文件上传:限制文件类型和大小
python复制class ProductImageForm(forms.ModelForm): class Meta: model = ProductImage fields = ['image'] def clean_image(self): image = self.cleaned_data.get('image') if image: if image.size > 2*1024*1024: raise ValidationError("图片大小不能超过2MB") if not image.name.lower().endswith(('.jpg', '.jpeg', '.png')): raise ValidationError("仅支持JPG/PNG格式") return image
5. 部署与监控方案
5.1 生产环境部署
我推荐使用Docker+Nginx+Gunicorn的组合:
dockerfile复制FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "core.wsgi"]
Nginx配置关键点:
nginx复制server {
listen 80;
server_name example.com;
location /static/ {
alias /app/staticfiles/;
}
location / {
proxy_pass http://web:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
5.2 监控与日志
-
错误监控:使用Sentry捕获异常
python复制import sentry_sdk sentry_sdk.init( dsn="your-dsn", integrations=[DjangoIntegration()], traces_sample_rate=1.0, ) -
性能监控:配置Django Debug Toolbar(开发环境)
python复制DEBUG_TOOLBAR_CONFIG = { 'SHOW_TOOLBAR_CALLBACK': lambda request: DEBUG, } -
日志配置:
python复制LOGGING = { 'version': 1, 'handlers': { 'file': { 'level': 'DEBUG', 'class': 'logging.FileHandler', 'filename': '/var/log/django/debug.log', }, }, 'loggers': { 'django': { 'handlers': ['file'], 'level': 'DEBUG', }, }, }
6. 项目扩展与二次开发建议
这个电商平台源码提供了良好的基础架构,可以根据业务需求进行多种扩展:
-
多商户支持:改造商品和订单模型,添加店铺关联
python复制class Shop(models.Model): owner = models.ForeignKey(User, on_delete=models.CASCADE) name = models.CharField(max_length=100) class Product(models.Model): shop = models.ForeignKey(Shop, on_delete=models.CASCADE) # 原有字段... -
国际化:添加多语言支持
python复制from django.utils.translation import gettext_lazy as _ class Product(models.Model): name = models.CharField(_('name'), max_length=200) -
API接口:使用DRF(Django REST Framework)构建移动端API
python复制from rest_framework import serializers, viewsets class ProductSerializer(serializers.ModelSerializer): class Meta: model = Product fields = '__all__' class ProductViewSet(viewsets.ModelViewSet): queryset = Product.objects.all() serializer_class = ProductSerializer -
推荐系统:基于用户行为实现简单推荐
python复制from django.db.models import Count def get_recommendations(user): # 获取用户购买过的商品类别 bought_categories = user.orders.values_list( 'items__product__category', flat=True ).distinct() # 推荐同类别热销商品 return Product.objects.filter( category__in=bought_categories ).annotate( sales_count=Count('order_items') ).order_by('-sales_count')[:5]
在实际开发中,我发现Django Admin的默认界面虽然功能强大,但对于电商后台管理来说还不够友好。我通过以下方式进行了增强:
python复制from django.contrib import admin
@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ['id', 'user', 'total_amount', 'status']
list_filter = ['status', 'created_at']
search_fields = ['user__username', 'id']
actions = ['mark_as_shipped']
def mark_as_shipped(self, request, queryset):
queryset.update(status='shipped')
mark_as_shipped.short_description = "标记为已发货"
对于需要处理大量数据的场景,比如生成销售报表,我建议使用Django的数据库路由实现读写分离,或者考虑使用专门的OLAP数据库。
