ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Django购物系统开发实战:从环境搭建到服务器部署

Django购物系统开发实战:从环境搭建到服务器部署 简介这是一套基于Python Django框架的商店购物系统毕业设计完整源码适合计算机相关专业学生、Django初/中级开发者参考学习。项目重点解决了传统电商系统中产品属性不灵活、无法支撑变体层次结构的问题通过模型设计直接反映物理属性避免使用EAV数据库反模式。压缩包共2.19MB包含427个文件其中166个Python文件承载核心业务逻辑101个HTML模板覆盖前端页面44个RST文档便于阅读项目说明另有JS、SCSS、PNG、国际化PO/MO等资源整体结构清晰可直接运行。目前已有191人学习/下载。通过该项目可掌握Django购物车的实现思路、商品模型与多规格变体设计、后台管理及订单流程等方法代码注释完整、目录组织规范适合作为毕业设计、课程设计或电商项目二次开发的基础模板。1. 得先认清为什么选Django购物系统当毕设而不是从零写框架毕设项目拿到手第一件事不是读代码而是先把环境跑通。很多基于Python Django的商店购物系统看起来完整实际会卡在Python版本、mysqlclient依赖、没执行数据迁移这几步。这套系统的好处是它把商品展示、加入购物车、生成订单、后台管理这一条链路写全了而且模型数量少关系清晰适合在答辩前做二次开发。下面直接从“跑起来”开始按环境、核心模块、改造、上线四个方向展开每一步都给出可执行的命令和参数。你不用改完所有代码才敢启动先跑通再按自己的论文需求改字段改逻辑是处理这类毕设项目最省时间的路径。2. 本地把购物系统跑起来Python、Django与依赖项的搭配2.1 先选对Python和Django版本省得后面重装依赖拿到“完整代码可直接运行”这句承诺时先别急着运行。最常见的问题是项目用的是老版本Django而你机器上是新Python。我的习惯是先看项目里的requirements.txt没有的话看manage.py里设置的默认配置再决定本地环境。Python 3.8配Django 4.2是可以长期用的组合Python 3.10、3.11也没问题。Django 5.0以上对Python 3.10以下不友好。如果这份毕设是前几年做的大概率是Django 2.2或3.2这两个版本在路由写法和时区配置上和老项目有差异。手里没有现成版本可以参考的时候我一般直接装Django 4.2.x配Python 3.10或3.11稳定性好网上教程也多。| 组合 | 适用情况 | 注意点 | | Python 3.8 Django 2.2 | 老代码、Python2迁移上来的 | 新语法支持有限不建议新开 | | Python 3.10 Django 4.2 | 大多数毕设二次开发推荐 | 支持新时区配置自带admin较完整 | | Python 3.12 Django 5.x | 新项目 | 部分mysqlclient包需要编译环境配置成本高 |2.2 安装Python并创建虚拟环境系统里已经装了Python的话先确认是3.8以上。Windows用户注意在Python安装时勾选“Add Python to PATH”。我会专门为这个毕设单独建一个虚拟环境避免污染全局site-packagespython3 -m venv shop_env source shop_env/bin/activate # Windows下执行 shop_env\Scripts\activate pip install --upgrade pip pip install django这里解释一下python3 -m venv shop_env创建了一个名为shop_env的虚拟环境里面会有独立的Python解释器和pip目录。进入虚拟环境之后再装的Django只对当前项目生效这样即使之后其他项目用了不同版本的Django也不会互相覆盖。常见的错误是漏掉source激活步骤直接运行pip install结果装到了全局环境后面runserver时又找不到模块。用VSCode调试时记得按下CtrlShiftP选择Python解释器指向shop_env里的python否则终端和调试器会用两套不同的环境。2.3 安装mysqlclient和缺失包避免启动就报错购物系统一般需要MySQL作为数据库。MySQL与Python之间的连接库是mysqlclient但这个包在部分系统上需要编译依赖这也是“完整代码运行不起来”的高发区。Linux下先安装系统库再装mysqlclientsudo apt-get install libmysqlclient-dev python3-dev pip install mysqlclientWindows用户一般直接pip install mysqlclient就能安装少数用Python 3.12的会遇到没有预编译wheel的情况建议换回Python 3.10或使用pymysql作为兼容方案。pymysql的接法是在项目包__init__.py里加上pymysql.install_as_MySQLdb()不过这只适合临时调试正式交毕设我还是推荐mysqlclient。安装完依赖后不要急着启动。先改settings.py里的数据库连接DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: shop_db, USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: {charset: utf8mb4}, } }数据库名、用户名、密码、端口这四个字段按你本机改。注意NAME指向的数据库必须先建好可以通过MySQL命令行执行CREATE DATABASE shop_db DEFAULT CHARACTER SET utf8mb4;创建。OPTIONS里的charset配置为utf8mb4是为了让商品名称、用户昵称里的emoji和生僻字不变成问号。2.4 第一次启动的最小命令集确认项目文件夹下有manage.py之后检查是否有一个独立的业务app目录。如果没有先运行python manage.py startapp shop这是Django创建app的标准命令有的话直接进入下一步。settings.py改完后按顺序执行以下几行python manage.py makemigrations python manage.py migrate python manage.py createsuperuser python manage.py runserver 127.0.0.1:8000makemigrations把模型类变化登记成迁移文件migrate把迁移写入数据库。如果项目里已经有迁移文件也可以直接执行migrate跳过makemigrations。createsuperuser会让你输入用户名、邮箱、密码这是登录后台的账号。runserver监听在127.0.0.1:8000浏览器打开http://127.0.0.1:8000/能看到商店首页就说明这套基于Django的商店购物系统已经在本地跑起来了。如果页面报错优先看终端里的Traceback90%的情况是数据库连不上或者没装mysqlclient。3. 拆开购物系统的四个核心商品、购物车、订单、用户3.1 商品模型字段类型与价格计算的边界购物系统里最基础的表是商品表。毕设里常见的商品模型大致长这样from django.db import models class Category(models.Model): name models.CharField(分类名称, max_length50) sort_order models.IntegerField(排序, default0) class Meta: ordering [sort_order] def __str__(self): return self.name class Product(models.Model): category models.ForeignKey(Category, on_deletemodels.CASCADE, verbose_name分类) name models.CharField(商品名称, max_length100) price models.DecimalField(单价, max_digits10, decimal_places2) stock models.PositiveIntegerField(库存, default0) main_image models.ImageField(主图, upload_toproducts/, blankTrue, nullTrue) status models.BooleanField(上架, defaultTrue) created_at models.DateTimeField(auto_now_addTrue) class Meta: ordering [-created_at] def __str__(self): return self.nameForeignKey里面的on_deletemodels.CASCADE表示分类删除时该分类下的商品一起删。对毕设来说这个参数最容易被答辩追问。price用DecimalField而不是FloatField原因是浮点数有二进制精度问题算总价时会出现19.98999999这种结果DecimalField配合decimal_places2能保证金额精确到分。stock用PositiveIntegerField是为了避免库存变负数数据库层面直接拦截非法数据。3.2 购物车用Session存还是有张CartItem表购物车有两种实现路线。只用session保存商品ID和数量代码量小但订单落到库里时需要再算一次价格用CartItem表保存用户与商品的关系代码稍多但可以记录勾选状态、商品快照后续做订单详情更方便。这里以数据库表为例class CartItem(models.Model): user models.ForeignKey(AUTH_USER_MODEL, on_deletemodels.CASCADE, verbose_name用户) product models.ForeignKey(Product, on_deletemodels.CASCADE, verbose_name商品) quantity models.PositiveIntegerField(数量, default1) selected models.BooleanField(选中状态, defaultTrue)cart_item的user关联Django自带用户表AUTH_USER_MODEL是一个设置项你可以换成自定义用户模型。add视图里需要检查同一个用户是否已经把这个商品加进购物车避免同一个product出现在同一用户的多行记录里然后用update_or_create更新数量def add_to_cart(request, product_id): product get_object_or_404(Product, pkproduct_id) if not product.status: return redirect(shop:product_list) cart_item, created CartItem.objects.update_or_create( userrequest.user, productproduct, defaults{quantity: F(quantity) 1} ) return redirect(shop:cart_detail)注意defaults里的F(quantity)是指让数据库对原quantity字段做加1操作不会出现并发下读旧值再写回的问题。created只是告诉你是新增还是更新不需要额外手动把quantity设置成1因为新增时模型默认值default1已经生效。用F表达式时不要尝试在Python侧先读取cart_item.quantity再加1这样会多一条SELECT而且在并发场景下结果不对。3.3 订单状态流转从购物车到待支付订单表一般包含订单号、用户、总金额、收货信息、状态。状态建议用IntegerField加choices不用字符串理由是数字状态在数据库里占空间小也方便扩展。常见状态值如下| 状态值 | 含义 | 下一步操作 | | 0 | 待支付 | 用户付费 | | 1 | 已支付 | 商家发货 | | 2 | 已发货 | 用户确认收货 | | 3 | 已收货 | 订单完成 | | 4 | 已取消 | 恢复库存 |创建订单时核心逻辑是先从CartItem取出当前用户所有selectedTrue的记录计算总价然后创建Order和OrderItem最后清空购物车。这块代码量不大但有一个必坑点订单一旦创建不应该再关联CartItem而是要把商品名称、单价、数量复制到OrderItem里作为快照。否则商品改了价格历史订单的金额也会跟着变对账时会很被动。3.4 Django执行查询-删除对象时要注意级联Django里最常用的删除写法是Model.objects.get(pk1).delete()和Model.objects.filter(...).delete()。对于购物系统的后台删除商品操作我不建议直接调delete()因为Product被CartItem和OrderItem外键引用时CASCADE会把历史订单明细也一起删掉。你可以在OrderItem外键和CartItem外键都改用on_deletemodels.PROTECT这样系统会拒绝删除有被引用的商品并抛出ProtectedError。# 在模型里这样改 product models.ForeignKey(Product, on_deletemodels.PROTECT, verbose_name商品)再用软删除代替硬删除更稳妥只需要给Product加一个is_active字段查询时默认过滤is_activeTrue后台删除变成置为False。这样商品不在商店展示历史订单数据却完整保留答辩时跟老师解释数据完整性和可追溯性是个加分点。删除对象一旦涉及外键就不要再裸用delete()先用orderitem_set.exists()确认引用关系。4. 把完整代码改成自己的毕设Admin、重定向与初始化数据4.1 改表结构后如何安全地多次迁移拿到完整代码后第一件事往往是想加上自己论文里独有的字段比如商品加入“产地”“上架时间范围”。修改模型后执行makemigrations要养成先看生成的迁移文件再执行migrate的习惯。python manage.py makemigrations python manage.py sqlmigrate 应用名 迁移文件名 python manage.py migratesqlmigrate只输出对应的SQL不会真正执行。这样能看到MySQL实际执行的ALTER TABLE语句可以提前发现是否有非空字段约束、默认值缺失的问题。新增非空字段时makemigrations通常会在命令行里询问默认值这时候直接给一个合理的默认值比交互更可控。最稳妥的做法是给新字段加上default或nullTrue例如color models.CharField(max_length20, default)。| 命令 | 作用 | | python manage.py makemigrations | 根据模型变化生成迁移文件 | | python manage.py sqlmigrate 应用 迁移名 | 查看迁移对应的SQL | | python manage.py migrate | 执行迁移 | | python manage.py showmigrations | 查看迁移执行情况 |迁移文件本身也要纳入版本管理不要让队友拿到项目后自己重新makemigrations因为产生的文件编号会出现重复。直接让他们执行migrate即可。4.2 Django admin界面美化把列表页变成可答辩的后台购物系统自带的admin可以满足基本增删改查但默认样式很简单。你不需要引入前后端分离先把admin的list_display配置好后台看起来就比空页面专业得多。# admin.py from django.contrib import admin from .models import Product, Order, OrderItem admin.register(Product) class ProductAdmin(admin.ModelAdmin): list_display (id, name, category, price, stock, status, created_at) list_filter (status, category) search_fields (name,) list_editable (price, stock, status) actions [set_all_off_shelf] admin.action(description批量下架) def set_all_off_shelf(self, request, queryset): queryset.update(statusFalse)常用配置里list_editable和list_display同时出现的字段不能是第一个字段否则Django会报错因为第一列默认作为详情链接入口。search_fields设置的是后台搜索框里可以模糊匹配的字段Django会生成LIKE查询所以只应放短字符串字段不要把TextField放进去。自定义action可以让批量操作直接出现在操作下拉框里上面代码执行的是对当前选中的商品一次性置为下架状态。如果是Windows或VSCode开发环境admin样式不生效时优先检查INSTALLED_APPS里有没有django.contrib.staticfiles以及浏览器Network面板里的静态文件请求是否404。404的原因往往是没有执行python manage.py collectstatic或DEBUGFalse时静态文件路径没配好。调试期间把DEBUG保持True即可生产部署时再关。4.3 Django重定向传递数据与reverse resolve的配套用法购物流程里提交订单后通常要跳转到支付页或订单详情页并在页面上显示“下单成功”提示。重定向时用redirect实现from django.shortcuts import redirect from django.urls import reverse def order_confirm(request): order_id create_order(request.user) return redirect(reverse(shop:order_success) f?order_id{order_id})这样跳转后订单数据没有丢query string里带着order_id。如果觉得查询参数太长可以在视图里直接放到sessionrequest.session[last_order_id] order_id跳转后再读出来并删除。用GET请求传参时要注意用户刷新页面会重复触发GET但不会重复创建订单因为创建订单的动作已经在前面执行完了这里只是读取。如果要严格防止刷新重复提交需要在创建订单前做一个幂等标识比如检查session里是否已有同一请求产生的订单号。reverse resolve这个报错通常是路由写法不一致。页面报NoReverseMatch时多半是模板里写错了{% url shop:cart_detail %}而urls.py实际定义的名字是cart-detail或cart_detail。用python manage.py show_urls需要安装django-extensions可以列出当前站点所有路由名直接对照去改模板name效率最高。4.4 生成演示数据让后台和首页看起来像真实商店毕设验收时老师打开首页如果看到空列表第一印象会差很多。用Django自己的ORM在shell里批量生成商品数据即可python manage.py shell进入交互式环境后写from shop.models import Category, Product c1, _ Category.objects.get_or_create(name数码, sort_order1) for i in range(1, 11): Product.objects.get_or_create( categoryc1, namef样品商品{i}, defaults{price: i * 10, stock: 50}, )get_or_create的defaults参数只在记录不存在时生效而查重字段是category和name避免了重复创建同名商品。批量生成后再用cart和order的接口生成一两条真实订单后台列表就有数据可看了。不止是空演示还建议准备一份只含少量数据的fixture提交时放到项目的fixtures目录下别人拿到项目后执行python manage.py loaddata sample_data.json就能复现你的所有演示内容。5. 上线前收紧一公里在宝塔部署Django购物系统5.1 用宝塔面板部署Django项目静态文件配置是关键这套购物系统验收地点如果不在本机需要部署到服务器。常见做法是宝塔部署Django项目先在服务器装好Python环境上传代码在代码目录里建虚拟环境安装依赖再用宝塔的Python项目管理器运行项目。部署前改造settings.pyDEBUG False ALLOWED_HOSTS [your.domain.com, 123.56.78.90] STATIC_ROOT /www/wwwroot/shop_project/staticfiles DATABASES { # 数据库账号改为服务器MySQL的账号不要用root远程登录 }DEBUG设为False后如果不把Static Root收集好admin的CSS和JS会全部丢失后台页面会变成纯HTML。执行python manage.py collectstatic会把所有app的静态文件复制到STATIC_ROOT指定目录宝塔站点配置里要把这个目录映射成静态URL。如果用的是Nginx通常要加一行location /static/ { alias /www/wwwroot/shop_project/staticfiles/; }否则后台样式仍然404。5.2 验收时不只点首页按这个清单过一次部署完成后我会按下面这个顺序快速验收购物系统的关键链路curl -I http://你的域名/admin/ curl -I http://你的域名/先看admin返回200还是302302说明跳到了登录页正常。再手动走一遍商品列表、加入购物车、结算下单确认没有出现500。常见错误是数据库迁移没执行页面直接报relation does not exist这时回到项目目录执行python manage.py migrate。还有一处是购物车页面用到了request.user如果Django启用了SESSION_COOKIE_SECURE未用HTTPS时会登录不上临时调试可把该选项关闭。提交前最后跑一次安全基线检查python manage.py check --deploy输出里如果提示SECRET_KEY被硬编码就改成从环境变量读取。按这条清单走完这套购物系统才算真正从“本地能跑”变成了“可以作为毕设交付”。本文还有配套的精品资源点击获取
返回列表