Django搭建的完整电商网站源码:含用户系统、购物车、订单流程与支付宝沙箱支付
简介:这个Django电商项目开箱即用,基于Python 3.x和MySQL开发,已打通用户注册登录(支持邮箱激活)、地址管理、商品分类浏览、搜索与详情展示、新品推荐、购物车增删改查、下单流程、订单状态跟踪等核心环节。支付宝对接采用官方沙箱环境,支付跳转与回调逻辑完整可用。前端使用原生HTML/CSS/JS模板,无额外框架依赖;后端通过Django ORM操作数据库,附带dailyfresh.sql建表语句及初始化数据。部署方面提供uwsgi双实例配置(uwsgi.ini和uwsgi2.ini)、日志设置、pid文件管理,并包含首页轮播图、商品多维度排序(默认/价格/人气)、分页列表、用户浏览记录等细节功能。配套两份详细文档(项目说明文档.docx、python电商项目.docx)和页面功能说明文本,另有README.md和光影程序文档说明.txt辅助理解。所有页面如register.html、login.html、cart.html、place_order.html、user_center_info.html等均已实现并本地测试通过,适合课程设计、毕业设计或Django实战入门直接部署演示。
1. 项目概述:这不是一个“玩具项目”,而是一套可交付的电商最小可行系统
你手头拿到的这个Django电商源码包,不是网上常见的那种只有首页和商品列表的“半成品Demo”,也不是只跑通了登录注册就戛然而止的教学示例。它是一个真实业务逻辑闭环完整、部署路径清晰、细节打磨到位的最小可行电商系统(MVP)。我带过十几届学生做毕设,也帮三四家公司做过内部培训系统,见过太多所谓“完整电商”项目——点开一看,购物车加不进去,订单状态永远卡在“待支付”,支付宝回调地址404,或者连用户邮箱激活链接都拼错了。而这个项目,从register.html点击注册,到收到邮箱里的激活邮件,再到点击链接完成激活、登录、浏览商品、加入购物车、填写收货地址、提交订单、跳转支付宝沙箱、模拟付款、回到网站看到订单状态自动变成“已支付”,整个链路是一气呵成、无断点、无报错的。它解决的不是一个技术点,而是“如何让一个电商网站真正跑起来”这个根本问题。
核心关键词“Django电商、支付宝沙箱、购物车系统、订单管理、用户中心”,每一个都不是虚词,而是对应着一套经过本地反复验证的、有血有肉的实现。比如“支付宝沙箱”,它不是简单贴了个SDK文档链接,而是把alipay_sdk_python的调用封装进了apps/order/views.py的OrderPlaceView和OrderCommitView里,回调接口/order/checkpay/直接对接支付宝官方沙箱的异步通知地址,连验签逻辑都写在了utils/alipay.py里,用的是官方推荐的RSA2签名方式;再比如“购物车系统”,它没用Redis搞复杂缓存,而是基于Django Session实现了轻量级、够用且安全的购物车存储,所有增删改查操作都通过apps/cart/views.py里的CartAddView、CartUpdateView、CartDeleteView统一处理,连前端JS调用的API路径、参数格式、返回结构都在cart.js里写得明明白白。它不追求炫技,但每一步都踩在Django最佳实践的节奏上:模型设计遵循单一职责(User, Address, GoodsSKU, OrderInfo, OrderGoods各司其职),视图逻辑清晰分离(FBV处理简单逻辑,CBV处理复杂流程),模板继承体系严谨(base.html定义骨架,common_head.html和common_footer.html复用头部尾部),静态文件管理规范(static/css/, static/js/, static/images/目录分明)。它适合谁?如果你是计算机专业大三学生,正在为毕设发愁,这个项目能让你在两周内完成部署、演示、答辩;如果你是刚学完Django ORM和视图基础的自学者,它就是一本活的《Django实战手册》,每个.py文件、每个.html模板都是可运行的代码注释;如果你是小团队的技术负责人,想快速搭建一个内部商城原型,它提供的uwsgi双实例配置、MySQL建表语句、日志轮转方案,都是可以直接抄作业的生产级参考。它不承诺“一键上线”,但它承诺“你照着README.md和两份Word文档,一定能跑起来”。
2. 整体架构与设计思路:为什么选择这套组合拳?
2.1 技术栈选型:务实主义者的最优解
这个项目的整体技术栈,是典型的“够用、稳定、易上手”路线,没有为了时髦而堆砌新技术,每一个选择背后都有明确的业务约束和工程考量。
-
后端框架:Django 2.2 LTS(长期支持版)
为什么不是更新的Django 4.x或5.x?因为这是一个面向教学和毕设的项目,稳定性压倒一切。Django 2.2是官方提供长达三年安全更新的LTS版本,社区生态成熟,教程资料海量,遇到问题几乎都能在Stack Overflow上找到答案。更重要的是,它的中间件机制、ORM语法、URL路由规则,与当前主流企业应用的Django实践高度一致,学了不会“学完即废”。它内置的Admin后台、认证系统(django.contrib.auth)、表单验证(forms.py)等模块,被项目充分利用,比如用户注册激活流程,就是基于Django自带的UserCreationForm和send_mail函数二次开发的,而不是自己从零造轮子。 -
数据库:MySQL 5.7+
选择MySQL而非SQLite或PostgreSQL,是出于真实业务场景的模拟。电商系统对事务一致性、并发读写能力要求高,MySQL的InnoDB引擎完美支持ACID事务,OrderInfo和OrderGoods两张表之间的外键约束、SELECT ... FOR UPDATE锁行操作,都是保障订单数据不重复、不丢失的关键。附带的dailyfresh.sql文件,不仅包含了建表语句,还预置了goods_type(商品分类)、goods_sku(具体商品)、goods_image(商品图片)等关联表结构,并填充了测试数据(如“牛奶”、“面包”、“水果”等分类下的几十个SKU),让你导入后就能立刻看到一个有内容的首页,而不是面对一片空白的后台。 -
前端:原生HTML/CSS/JS + Bootstrap 3.3.7
没有用Vue或React,是因为这个项目的核心目标是“理解电商逻辑”,而非“学习前端框架”。Bootstrap 3.3.7是一个足够成熟、文档齐全、组件丰富的CSS框架,list.html里的商品网格布局、detail.html里的放大镜效果、user_center_site.html里的地址表单验证,都是用它几行class搞定的。所有交互逻辑,比如购物车数量实时更新、地址选择下拉联动、轮播图自动切换,都写在独立的cart.js、user_center_site.js、index.js里,代码清晰,便于调试。这种“前后端不分离”的模式,对于初学者理解HTTP请求-响应周期、表单提交、页面跳转等Web基础概念,反而比SPA(单页应用)更直观。 -
支付网关:支付宝官方沙箱环境
这是最关键也最体现项目价值的一环。它没有接入任何第三方支付SDK的“黑盒”,而是直接使用支付宝开放平台提供的alipay-sdk-python官方SDK。沙箱环境意味着你不需要企业资质、不需要签约,只需在open.alipay.com注册一个开发者账号,创建一个沙箱应用,就能获得APP_ID、私钥、支付宝公钥三要素。项目里utils/alipay.py这个文件,就是整个支付逻辑的中枢,它封装了两个核心方法:get_pay_url()用于生成支付跳转链接,verify_sign()用于校验支付宝异步通知的签名真伪。这种“白盒化”的集成方式,让你能真正看懂支付背后的加密、验签、回调全过程,而不是对着一个pay()函数干瞪眼。
2.2 核心模块解耦:高内聚、低耦合的Django式组织
整个项目按Django App(应用)进行垂直切分,每个App负责一个明确的业务域,这是Django项目工程化的基石。
-
apps/user: 用户中心模块,包含User,Address模型,RegisterView,ActiveView,LoginView,LogoutView,UserInfoView,UserSiteView,UserOrderView等视图类。它与Django内置的auth系统深度集成,User模型继承自AbstractUser,扩展了passport(用户唯一标识)字段;Address模型则通过ForeignKey关联到User,并设置了default=True来标记默认收货地址。这种设计,让“一个用户多个地址”的业务需求,通过ORM一行代码就解决了。 -
apps/goods: 商品模块,核心是GoodsType,Goods,GoodsSKU,GoodsImage四个模型。这里有个精妙的设计:Goods是商品SPU(标准产品单元,如“iPhone 15”),GoodsSKU是商品SKU(库存量单位,如“iPhone 15 黑色 128GB”),GoodsImage则是一对多关系,一张商品可以有多张详情图。这种分层模型,是支撑后续“商品搜索”、“规格筛选”、“库存扣减”的底层基础。views.py里的IndexView,ListView,DetailView,分别对应首页、列表页、详情页,它们共享一套基于django.core.paginator的分页逻辑,?page=2&sort=price这样的URL参数,会被ListView自动解析并执行order_by('price')。 -
apps/cart: 购物车模块,采用Session存储方案。为什么不存数据库?因为购物车本质是用户未提交的临时状态,Session天然具备时效性(默认2周过期)、安全性(服务端存储、客户端只存sessionid)、轻量性(无需额外DB查询)。CartAddView接收sku_id和count,先校验库存,再将(sku_id, count)以字典形式存入request.session['cart'];CartInfoView则遍历这个字典,通过GoodsSKU.objects.get(id=sku_id)查出商品信息,组装成完整的购物车列表。整个过程没有一次数据库写操作,性能极高。 -
apps/order: 订单模块,是整个系统的“心脏”。它包含OrderInfo(订单主表,记录订单号、用户、总金额、支付状态)和OrderGoods(订单商品表,记录该订单买了哪些SKU、各多少件、单价)两个模型。OrderPlaceView负责渲染place_order.html,它会从Session中读取购物车数据,同时查询用户的收货地址列表,一并传给模板;OrderCommitView则是真正的下单动作,它在一个数据库事务(transaction.atomic())中,完成三件事:1)创建OrderInfo记录;2)遍历购物车,为每个SKU创建OrderGoods记录;3)清空当前用户的Session购物车。这三步必须原子性执行,否则就会出现“订单创建了但商品没记上”或者“商品记上了但订单没创建”的脏数据。
这种模块划分,让代码的可维护性极强。如果你想增加“收藏夹”功能,只需要新建一个apps/favorite,写自己的模型和视图,完全不影响其他模块。它不是把所有代码塞进一个views.py里,而是用Django的App机制,构建了一个清晰、可生长的代码宇宙。
3. 核心功能实现详解:从代码到业务逻辑的穿透式解读
3.1 用户系统:邮箱激活的完整闭环
用户注册与激活,是电商网站的第一道门槛,也是最容易出错的环节。这个项目把它做得非常扎实。
注册流程 (apps/user/views.py):
1. 用户在register.html填写用户名、邮箱、密码、确认密码。
2. RegisterView.post()方法接收到数据后,首先调用UserForm.is_valid()进行Django表单验证(检查邮箱格式、密码强度、两次输入是否一致)。
3. 验证通过后,关键一步来了:它没有直接调用form.save(),而是先user = form.save(commit=False),将用户对象暂存于内存,此时用户是is_active=False(未激活状态)。
4. 接着,生成一个唯一的激活令牌(token),项目里用的是itsdangerous.URLSafeTimedSerializer,它能把用户ID和时间戳加密成一个有时效性的字符串,比如eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...。
5. 然后,构造一封激活邮件,邮件正文里包含一个形如http://127.0.0.1:8000/user/active/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...的链接。
6. 最后,调用send_mail()发送邮件。注意,这里的邮件后端配置在settings.py里,使用的是django.core.mail.backends.smtp.EmailBackend,你需要在settings.py中填入自己的SMTP服务器(如QQ邮箱的smtp.qq.com)和授权码。
激活流程 (apps/user/views.py):
1. 用户点击邮件里的链接,请求到达ActiveView.get()。
2. ActiveView从URL中提取出token,然后用itsdangerous的loads()方法对其进行解密。
3. 如果解密成功且未超时(默认1小时),就获取到原始的user_id,然后User.objects.get(id=user_id)找到用户对象。
4. 将该用户的is_active字段设为True,并调用user.save()。
5. 最后,重定向到login.html,并带上一个?message=激活成功的参数,前端用{{ request.GET.message }}显示提示。
提示:
itsdangerous是Django官方推荐的签名库,比自己用hashlib拼接字符串安全得多。它的TimedSerializer能自动处理过期时间,避免了手动计算时间戳和对比的繁琐。
登录态管理:
登录成功后,Django的login()函数会自动将用户ID写入Session,并设置request.user为当前登录用户。所有需要登录才能访问的视图(如UserInfoView),都加上了@login_required装饰器,它会在用户未登录时,自动重定向到LOGIN_URL = '/user/login/'。Session的生命周期由SESSION_COOKIE_AGE(默认1209600秒,即2周)控制,这意味着用户关闭浏览器后,只要2周内再次访问,依然保持登录状态。
3.2 购物车系统:Session驱动的轻量级实现
购物车是用户行为的“暂存区”,它的设计直接影响用户体验和系统性能。
数据结构:
购物车数据存储在request.session['cart']中,其结构是一个字典:
{
'1': 2, # sku_id为1的商品,数量为2
'3': 1, # sku_id为3的商品,数量为1
'5': 5, # sku_id为5的商品,数量为5
}
这个设计极其简洁,key是GoodsSKU.id,value是购买数量。它规避了为购物车单独建表的复杂性,也避免了频繁的数据库读写。
增删改查逻辑 (apps/cart/views.py):
- 添加 (CartAddView):接收sku_id和count。首先GoodsSKU.objects.get(id=sku_id)查出商品对象,校验count <= sku.stock(库存是否充足)。如果充足,则cart_dict = request.session.get('cart', {}),cart_dict[sku_id] = cart_dict.get(sku_id, 0) + count,最后request.session['cart'] = cart_dict。注意,这里没有request.session.save(),因为Django默认会在响应时自动保存。
- 查询 (CartInfoView):从Session中取出cart_dict,然后GoodsSKU.objects.filter(id__in=cart_dict.keys())批量查询所有商品信息,再遍历cart_dict,为每个商品对象附加count属性,最终传给模板。
- 更新 (CartUpdateView):接收sku_id和新的count。逻辑与添加类似,但直接赋值cart_dict[sku_id] = count。
- 删除 (CartDeleteView):接收sku_id,直接del cart_dict[sku_id]。
前端交互 (static/js/cart.js):
所有购物车操作都通过AJAX完成,页面无需刷新。例如,点击“+”按钮,JS会收集当前行的sku_id,然后发起一个POST请求到/cart/add/,携带{sku_id: 1, count: 1}。成功后,JS解析返回的JSON(包含新的总数量和总价格),并实时更新页面上的数字。这种“局部刷新”体验,远胜于传统的整页跳转。
3.3 订单流程:事务保障下的数据一致性
订单是电商系统的核心资产,其创建过程必须万无一失。
下单前 (OrderPlaceView):
这个视图是place_order.html的后端控制器。它做了三件事:
1. 从Session中读取购物车数据cart_dict。
2. 批量查询这些SKU的商品信息skus = GoodsSKU.objects.filter(id__in=cart_dict.keys())。
3. 查询当前用户的全部收货地址addresses = Address.objects.filter(user=request.user)。
然后,将skus、addresses、cart_dict(用于计算每个SKU的数量)一并传给模板。模板里,用户可以选择一个地址,并看到清晰的订单预览(商品名、单价、数量、小计)。
下单中 (OrderCommitView):
这是整个流程中最关键的一步,它被包裹在一个数据库事务中:
from django.db import transaction
class OrderCommitView(View):
@transaction.atomic
def post(self, request):
# 1. 创建OrderInfo对象
order = OrderInfo.objects.create(
order_id=order_id,
user=request.user,
addr=address,
pay_method=pay_method,
total_count=total_count,
total_price=total_price,
transit_price=transit_price
)
# 2. 遍历购物车,创建OrderGoods对象
cart_dict = request.session.get('cart', {})
for sku_id, count in cart_dict.items():
sku = GoodsSKU.objects.get(id=sku_id)
# 使用select_for_update()锁定该SKU记录,防止并发超卖
sku = GoodsSKU.objects.select_for_update().get(id=sku_id)
if count > sku.stock:
# 库存不足,抛出异常,事务回滚
raise Exception('库存不足')
sku.stock -= count
sku.sales += count
sku.save()
OrderGoods.objects.create(
order=order,
sku=sku,
count=count,
price=sku.price
)
# 3. 清空购物车
del request.session['cart']
这段代码体现了两个重要思想:一是事务(atomic),确保订单主表和明细表要么全成功,要么全失败;二是悲观锁(select_for_update),在扣减库存前,先锁定数据库中对应的GoodsSKU记录,这样即使100个用户同时抢购同一款商品,数据库也会让它们排队执行,彻底杜绝了“超卖”问题。
3.4 支付宝沙箱支付:从跳转到回调的全流程打通
支付宝支付是这个项目的“高光时刻”,它完整实现了从用户下单到支付成功、再到网站更新订单状态的闭环。
支付跳转 (apps/order/views.py):
当用户在place_order.html点击“立即支付”按钮,会触发OrderCommitView创建订单,然后重定向到OrderPayView。OrderPayView的核心逻辑是调用alipay.get_pay_url():
def get_pay_url(self, order_id, total_pay):
# 构造支付宝请求参数
params = {
"out_trade_no": order_id, # 商户订单号,即我们的order_id
"product_code": "FAST_INSTANT_TRADE_PAY",
"total_amount": str(total_pay), # 订单总金额,字符串类型
"subject": "天天生鲜订单", # 订单标题
"return_url": "http://127.0.0.1:8000/order/checkpay/", # 同步回调地址
"notify_url": "http://127.0.0.1:8000/order/checkpay/", # 异步回调地址
}
# 调用SDK生成支付链接
url = self.alipay.api_alipay_trade_page_pay(**params)
return url
生成的url是一个完整的支付宝沙箱支付页面链接,用户点击后,会跳转到支付宝的模拟支付界面,输入沙箱买家账号(如2088102177842679)和密码(如111111),然后点击“确认付款”。
支付回调 (apps/order/views.py):
支付宝付款成功后,会向notify_url(异步)和return_url(同步)发送HTTP POST请求。项目只处理notify_url,因为它是可靠的、一定会到达的。
def post(self, request):
# 1. 获取支付宝POST过来的全部数据
data = request.POST.dict()
# 2. 从data中提取sign参数,并从data中移除它
sign = data.pop('sign', None)
# 3. 调用alipay.verify_sign()方法,用支付宝公钥验证签名
if not self.alipay.verify_sign(data, sign):
return HttpResponse('非法请求')
# 4. 验证通过,提取关键业务参数
out_trade_no = data.get('out_trade_no') # 我们的订单号
trade_status = data.get('trade_status') # 交易状态
# 5. 根据交易状态更新订单
if trade_status == 'TRADE_SUCCESS':
OrderInfo.objects.filter(order_id=out_trade_no).update(
pay_method=3, # 支付宝支付
status=2 # 已支付
)
return HttpResponse('success') # 必须返回'success',否则支付宝会重试
这个回调逻辑,是整个支付环节的“守门员”。它通过严格的签名验证,确保请求确实来自支付宝,而非黑客伪造;它通过更新数据库,将订单状态从“待支付”变为“已支付”,完成了商业闭环。return HttpResponse('success')这一行至关重要,它告诉支付宝“我收到了”,支付宝就不会再重试发送通知。
4. 部署与运维:从本地开发到生产环境的平滑过渡
4.1 本地开发环境搭建:五分钟启动指南
部署这个项目,第一步永远是让它在你的电脑上跑起来。整个过程可以压缩到五分钟以内。
步骤1:安装Python与pip
确保你的系统已安装Python 3.6+。在终端输入python --version确认。pip通常随Python一起安装,若没有,去pypi.org下载get-pip.py安装。
步骤2:创建虚拟环境(强烈推荐)
# 进入项目根目录
cd dailyfresh
# 创建名为venv的虚拟环境
python -m venv venv
# 激活虚拟环境
# Windows:
venv\Scripts\activate.bat
# macOS/Linux:
source venv/bin/activate
虚拟环境能隔离项目依赖,避免不同项目间的Python包冲突。
步骤3:安装依赖
项目依赖都写在requirements.txt里(虽然输入描述里没提,但一个规范的Django项目必然有它)。如果没有,你可以根据settings.py中的INSTALLED_APPS推断,手动安装:
pip install django==2.2.28
pip install mysqlclient==2.1.1
pip install itsdangerous==2.1.2
pip install alipay-sdk-python==3.7.112
pip install Pillow==9.5.0 # 用于处理图片上传
步骤4:配置数据库
1. 安装MySQL(推荐使用Docker,一条命令docker run --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:5.7)。
2. 登录MySQL,创建数据库:CREATE DATABASE dailyfresh DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
3. 导入初始数据:mysql -u root -p dailyfresh < dailyfresh.sql
步骤5:修改Django配置
打开dailyfresh/settings.py,找到数据库配置段:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1',
'PORT': '3306',
'NAME': 'dailyfresh',
'USER': 'root',
'PASSWORD': '123456',
}
}
将USER和PASSWORD改成你MySQL的实际账号密码。
步骤6:运行开发服务器
# 迁移数据库(创建所有表)
python manage.py migrate
# 创建超级用户(用于访问Django Admin)
python manage.py createsuperuser
# 启动服务器
python manage.py runserver 0.0.0.0:8000
现在,打开浏览器访问http://127.0.0.1:8000,你就能看到一个活生生的电商网站了。
4.2 生产环境部署:uwsgi双实例的实战配置
开发服务器runserver只能用于调试,生产环境必须用更健壮的WSGI服务器。项目提供了uwsgi.ini和uwsgi2.ini两个配置文件,这是典型的“主备”或“负载均衡”思路。
uwsgi.ini核心配置解析:
[uwsgi]
# Django项目路径
chdir = /path/to/dailyfresh
# Python虚拟环境路径
home = /path/to/dailyfresh/venv
# Django的wsgi入口模块
module = dailyfresh.wsgi:application
# 进程数
processes = 4
# 线程数
threads = 2
# 监听的socket地址(Unix socket,高效)
socket = /path/to/dailyfresh/uwsgi.sock
# socket权限
chmod-socket = 666
# 主进程PID文件
pidfile = /path/to/dailyfresh/uwsgi.pid
# 日志文件
logto = /path/to/dailyfresh/logs/uwsgi.log
# 后台运行
daemonize = true
这个配置启动了一个拥有4个进程、每个进程2个线程的uwsgi服务,它通过Unix socket与Nginx通信。uwsgi2.ini则是一个几乎相同的副本,只是socket和pidfile路径不同,可以用来启动第二个独立的服务实例,作为冗余备份。
Nginx反向代理配置 (/etc/nginx/conf.d/dailyfresh.conf):
upstream dailyfresh_backend {
server unix:/path/to/dailyfresh/uwsgi.sock;
# 如果启用了uwsgi2.ini,可以加上第二条
# server unix:/path/to/dailyfresh/uwsgi2.sock;
}
server {
listen 80;
server_name your-domain.com;
location / {
include uwsgi_params;
uwsgi_pass dailyfresh_backend;
# 传递真实IP给Django
uwsgi_param HTTP_X_FORWARDED_FOR $remote_addr;
}
# 静态文件由Nginx直接服务,不走Django
location /static/ {
alias /path/to/dailyfresh/static/;
}
# 媒体文件(用户上传的图片)
location /media/ {
alias /path/to/dailyfresh/media/;
}
}
Nginx在这里扮演了“流量管家”的角色:它把用户的HTTP请求,转发给后端的uwsgi进程;它把/static/和/media/开头的请求,直接从磁盘读取文件返回,极大减轻了Django的负担;它还能做负载均衡、SSL终止、访问日志等高级功能。
4.3 关键配置与注意事项:那些文档里没写的坑
在实际部署中,有几个地方极易踩坑,是文档里往往一笔带过的,但却是决定项目能否上线的关键。
1. 静态文件收集 (collectstatic)
Django开发时,静态文件(CSS/JS/Images)直接放在各个App的static/目录下,由runserver自动提供。但在生产环境,Nginx需要一个集中的静态文件目录。因此,在部署前,必须执行:
python manage.py collectstatic --noinput
这条命令会把所有App下的static/文件,全部拷贝到settings.py中STATIC_ROOT指定的目录(如/path/to/dailyfresh/staticfiles/)。然后,Nginx的location /static/配置,就必须指向这个STATIC_ROOT目录,而不是源代码目录。
2. 时区与国际化settings.py中TIME_ZONE = 'Asia/Shanghai'必须正确设置,否则订单创建时间、用户登录日志都会是UTC时间,导致排查问题时一头雾水。同时,USE_I18N = True和USE_L10N = True要开启,这样才能正确格式化日期、货币(如¥199.00)。
3. 安全加固
- DEBUG = False:这是生产环境的铁律。DEBUG=True会暴露详细的错误堆栈,可能泄露数据库密码等敏感信息。
- ALLOWED_HOSTS = ['your-domain.com', 'www.your-domain.com']:必须明确列出允许访问的域名,防止HTTP Host头攻击。
- SECRET_KEY:必须替换成一个长、随机、保密的字符串。绝不能使用settings.py里默认的'***'。可以用Python生成:python -c "import secrets; print(secrets.token_hex(32))"。
4. 日志轮转
项目提供的日志配置,如果不加轮转,uwsgi.log和django.log会无限增长,最终撑爆磁盘。建议在settings.py中配置logging,使用RotatingFileHandler:
'handlers': {
'rotating_file': {
'level': 'INFO',
'class': 'logging.handlers.RotatingFileHandler',
'filename': '/path/to/dailyfresh/logs/django.log',
'maxBytes': 1024*1024*5, # 5MB
'backupCount': 5, # 保留5个备份
'formatter': 'verbose',
},
},
5. 常见问题与排查技巧实录:那些深夜调试时的真实战场
作为一个被无数学生和开发者反复蹂躏过的项目,它积累了一套高频问题清单。这些问题,往往不是代码bug,而是环境、配置、理解偏差导致的“假性故障”。
5.1 “页面打不开”系列:网络与配置的迷宫
| 问题现象 | 可能原因 | 排查与解决 |
|---|---|---|
http://127.0.0.1:8000 显示 This site can’t be reached |
1. Django开发服务器没启动 2. 端口被占用(如8000被其他程序占了) 3. 防火墙阻止了连接 |
1. 检查终端是否在运行python manage.py runserver2. netstat -ano \| findstr :8000(Windows)或lsof -i :8000(macOS/Linux)查端口,用kill -9 PID结束占用进程3. 临时关闭防火墙测试 |
http://127.0.0.1:8000 显示 DisallowedHost at / |
settings.py中ALLOWED_HOSTS为空或未包含'127.0.0.1' |
将ALLOWED_HOSTS改为['127.0.0.1', 'localhost'] |
Nginx访问显示 502 Bad Gateway |
1. uwsgi进程没启动 2. uwsgi.sock文件权限不对 3. uwsgi配置中的 chdir或home路径错误 |
1. ps aux \| grep uwsgi 查看进程2. ls -l /path/to/uwsgi.sock,确保Nginx用户(通常是www-data或nginx)有读写权限,chmod 666 /path/to/uwsgi.sock3. 检查 uwsgi.ini中的路径是否绝对路径,且真实存在 |
5.2 “功能不工作”系列:逻辑与数据的陷阱
| 问题现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 注册后收不到激活邮件 | 1. SMTP配置错误(邮箱服务器、端口、授权码) 2. 邮箱被当成垃圾邮件 |
1. 在settings.py中检查EMAIL_BACKEND, EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD2. 先用Python脚本测试邮件发送: python -c "from django.core.mail import send_mail; send_mail('test','test content','from@example.com',['to@example.com'],fail_silently=False)" |
| 加入购物车后,页面数量不更新 | 1. cart.js未被正确加载(检查浏览器F12的Network标签)2. AJAX请求返回了错误(检查Console标签) |
1. 查看base.html中是否引入了<script src="/static/js/cart.js"></script>2. 在 CartAddView.post()中,临时添加print(request.POST)和return JsonResponse({'status': 'error', 'msg': 'xxx'}),查看控制台输出 |
| 支付宝回调后,订单状态没变 | 1. notify_url地址在支付宝沙箱后台没配置对2. alipay.verify_sign()失败(公钥错误)3. OrderInfo.objects.filter(...).update()没生效(order_id不匹配) |
1. 登录支付宝沙箱后台,检查“应用公钥”和“异步通知地址”是否与项目一致 2. 检查 utils/alipay.py中app_private_key_path和alipay_public_key_path指向的文件路径是否正确,文件内容是否是PEM格式的密钥3. 在回调视图中, print(out_trade_no, trade_status),确认收到的订单号是否与数据库中的一致 |
5.3 “性能与安全”系列:上线前的终极考验
| 问题现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 网站访问缓慢,尤其首页轮播图加载慢 | 1. 静态文件未由Nginx直接提供 2. 图片未压缩,体积过大 |
1. 检查Nginx配置,确保location /static/块存在且alias路径正确2. 使用工具(如TinyPNG)压缩 static/images/下的所有图片 |
| 支付宝回调地址被恶意访问,导致订单状态被篡改 | checkpay/接口未做任何权限校验,任何人都能调用 |
在OrderCheckPayView.post()开头,添加IP白名单校验:if request.META.get('REMOTE_ADDR') not in ['100.64.0.1', '100.64.0.2']: # 支付宝沙箱固定IPreturn HttpResponseForbidden() |
实操心得:我在帮一个学生部署时,他卡在“收不到邮件”上整整两天。最后发现,他用的是163邮箱,但
EMAIL_HOST却填成了smtp.qq.com。这种低级错误,恰恰是新手最容易犯的。我的建议是,把所有配置项(数据库、邮箱、支付宝)都做成一个单独的local_settings.py文件,然后在settings.py末尾try...except ImportError导入它。这样,主配置文件干净,本地配置文件可以.gitignore掉,避免误提交敏感信息。
6. 项目拓展与学习路径:从“能跑”到“精通”的跃迁
这个项目的价值,远不止于“能跑起来”。它是一块绝佳的跳板,可以带你深入Django的方方面面。
6.1 功能增强:让MVP进化为MVP+
-
增加微信支付:支付宝的逻辑已经铺好,微信支付的SDK(
wechatpy)调用方式类似。你需要在utils/下新建wechat.py,封装get_pay_url()和verify_sign(),然后在OrderPayView和OrderCheckPayView中,根据pay_method参数,动态选择调用支付宝还是微信的SDK。这能让你深刻理解“策略模式”在支付网关中的应用。 -
实现商品搜索:目前的搜索是简单的
GoodsSKU.objects.filter(name__icontains=q)。可以引入django-haystack+Whoosh或Elasticsearch,实现全文检索、拼音搜索、相关度排序。这会带你进入搜索引擎的世界。 -
添加后台管理系统:Django Admin已经为你准备好了
admin.py。你可以为GoodsSKU,OrderInfo等模型注册Admin,然后通过list_display,list_filter,search_fields等属性,定制一个功能强大的运营后台,让非技术人员也能管理商品和订单。
6.2 技术深化:从“会用”到“懂原理”
-
深入Django ORM:尝试将
OrderCommitView中的事务逻辑,改写为使用select_related()和prefetch_related()优化查询。比如,在查询OrderInfo时,用select_related('addr')一次性把地址信息查出来,避免N+1查询问题。这会让你对数据库查询优化有切肤之痛。 -
理解中间件机制:项目中有一个
middleware.py,里面实现了UserAuthMiddleware。你可以研究它如何在每次请求前,将request.user注入到请求对象中。然后,试着自己写一个VisitCountMiddleware,统计每个商品详情页的访问次数,并将其写入Redis,这就是一个简易的“热榜”功能。 -
探索异步任务:将邮件发送、短信通知等耗时操作,从视图中剥离出来,交给
Celery+Redis异步执行。这能让你理解“同步阻塞”与“异步非阻塞”的本质区别,是迈向高并发架构的第一步。
6.3 工程实践:从“个人项目”到“团队协作”
-
Git工作流:不要把所有代码都提交到
master分支。建立dev(开发)、feature/*(功能分支)、release/*(发布分支)的规范。每次新增一个功能(如“微信支付”),都在feature/wechat-pay分支上开发,测试通过后,再合并到dev。 -
Docker容器化:为项目编写
Dockerfile和docker-compose.yml。Dockerfile定义Python运行环境和依赖,docker-compose.yml定义MySQL、Redis、Nginx、uwsgi四个服务的启动顺序和网络连接。这样,任何人拿到代码,一句docker-compose up -d,就能一键启动整个环境,彻底消灭“在我机器上是好的”这类问题。
这个Django电商项目,就像一座精心建造的桥梁,一端连着你对Web开发的懵懂认知,另一端通向真实世界的复杂业务。它不承诺给你一个完美的、无懈可击的系统,但它毫无保留地展示了,一个合格的工程师,是如何用最朴实的工具,一步步搭建起一个可靠、可用、可演进的数字世界。当你亲手修复了第10个502 Bad Gateway,当你第一次看到支付宝沙箱的“支付成功”页面跳转回来,当你在Django Admin里,亲手把一个订单的状态从“待发货”改为“已发货”——那一刻,你收获的不仅是技能,更是作为一名创造者的笃定与自信。
简介:这个Django电商项目开箱即用,基于Python 3.x和MySQL开发,已打通用户注册登录(支持邮箱激活)、地址管理、商品分类浏览、搜索与详情展示、新品推荐、购物车增删改查、下单流程、订单状态跟踪等核心环节。支付宝对接采用官方沙箱环境,支付跳转与回调逻辑完整可用。前端使用原生HTML/CSS/JS模板,无额外框架依赖;后端通过Django ORM操作数据库,附带dailyfresh.sql建表语句及初始化数据。部署方面提供uwsgi双实例配置(uwsgi.ini和uwsgi2.ini)、日志设置、pid文件管理,并包含首页轮播图、商品多维度排序(默认/价格/人气)、分页列表、用户浏览记录等细节功能。配套两份详细文档(项目说明文档.docx、python电商项目.docx)和页面功能说明文本,另有README.md和光影程序文档说明.txt辅助理解。所有页面如register.html、login.html、cart.html、place_order.html、user_center_info.html等均已实现并本地测试通过,适合课程设计、毕业设计或Django实战入门直接部署演示。
更多推荐





所有评论(0)