拓冰建站拓冰建站
首页 / 资讯中心 / 正文

从manage.py到生产部署:美多商城Django项目源码解析

简介这是一份基于Django框架与Python语言开发的美多商城项目源码面向计算机相关专业在校学生、老师及企业开发者尤其适合作为毕业设计、课程设计、课程大作业或项目初期立项演示的参考模板也推荐给希望通过完整项目代码加深理解的Python/Django进阶学习者。资源压缩包共6个文件、约3KB主体为5个Python源码文件涵盖Django项目的核心配置、URL路由、WSGI入口与项目管理逻辑另有1个sqlite3数据库文件便于下载后直接查看初始数据表结构或本地运行调试。从内容预览看项目具备完整的Django工程目录结构包含项目核心配置包、数据库文件与可执行管理脚本能够完整体现商城类Web应用的工程组织方式与请求处理链路。项目源码已经过测试运行验证功能稳定可靠目前已有1034人学习浏览。读者拿到后既可快速用于项目演示、课设验收等场景也可基于现有代码进行二次开发逐步扩展商品、购物车或订单等业务模块。1. 从manage.py开始认识美多商城拿到压缩包后最先要看的不是代码而是根目录下的manage.py。只要有这个文件就意味着这是一个完整的Django项目而不是一堆零散页面。美多商城是典型的电商类Django实战项目用户、商品、购物车、订单这些核心业务都有对应的模块实现比较适合用来做课程设计、毕业设计演示或者作为二次开发基线。对于熟悉Python Flask的开发者也值得拆一遍可以一次性看清Django的模型、视图、模板和后台管理是怎么串起来的。接下来我会从项目结构说起逐步拆到数据库、用户认证和订单逻辑最后聊生产环境的部署切换。2. Django项目结构与启动前的配置细节2.1 meiduo_mall目录里每个文件的作用解压之后看到的目录层级很直接外层是manage.py和db.sqlite3内层是一个名为meiduo_mall的配置包。Django的manage.py相当于项目的命令行入口创建应用、运行开发服务器、执行数据库迁移都需要通过它。真正的项目配置都在meiduo_mall目录下其中settings.py控制所有全局配置urls.py负责URL路由分发wsgi.py是部署时的WSGI入口。如果这个项目将来要放在uWSGI或gunicorn下运行wsgi.py就是启动脚本必须引用的模块。我一般会先用tree命令看一眼结构确认项目里是否有多个app目录比如users、goods、orders因为美多商城这类课程项目经常会拆成多个子应用而压缩包里的目录如果被人刻意精简过可能会丢失一部分app。拿到代码后建议先执行一次runserver看能否正常启动再决定是否补依赖。$ unzip 美多商城项目源码.zip $ cd meiduo_mall $ tree -L 2 . ├── manage.py ├── db.sqlite3 └── meiduo_mall ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py参数说明-L 2表示只展示两层目录避免输出的内容过深。这里的db.sqlite3是SQLite的数据库文件Django默认配置下所有模型表都会落在这个文件里它不是一个简单的缓存文件而是完整的数据库压缩包里带上它说明项目已经做过至少一次migrate可以直接读取已有数据。2.2 Django安装与基本迁移命令在启动项目之前先确认本地Python和Django环境可用。如果你是从python安装教程装好的Python 3.10建议创建独立虚拟环境再安装Django避免和系统依赖冲突。常见做法是python -m venv venv source venv/bin/activate # Windows下使用 venv\Scripts\activate pip install django python manage.py migrate python manage.py runserver 0.0.0.0:8000这里的migrate会读取settings.py中INSTALLED_APPS列表把django.contrib.auth、admin、contenttypes等内置应用的表结构写入db.sqlite3。runserver 0.0.0.0:8000表示监听所有网卡地址本机访问http://127.0.0.1:8000同一局域网内也可通过电脑的IP访问。如果migrate之后出现了关于app迁移文件的警告多半是源码里某个app缺少migrations目录需要手动执行makemigrations。运行起来后如果页面能打开但CSS样式全部丢失不要急着改模板优先检查settings.py里的STATIC_URL和STATICFILES_DIRS。最常见的问题是把静态文件路径写成了绝对路径导致Django开发服务器找不到资源。可以先用浏览器开发者工具看静态资源的请求状态码404就说明路径配置有问题。提示如果要在现有源码上新增一个业务模块执行python manage.py startapp couponDjango会自动创建包含models.py、views.py、migrations目录的app骨架这是Django创建app的标准做法。2.3 settings.py和urls.py的关键配置点打开settings.py我建议重点关注三处INSTALLED_APPS、DATABASES、AUTH_USER_MODEL。INSTALLED_APPS决定哪些模块能被migrate识别如果项目里已经建了商品、订单相关的app这里必须能看到对应的app名称。DATABASES默认使用SQLite这也是课程项目最常见的配置因为免安装、容易提交作业。AUTH_USER_MODEL则是一个很容易踩坑的关键项如果开发者在代码里通过AbstractUser扩展了用户名和手机号字段那么这个配置项就必须指向自定义用户模型比如INSTALLED_APPS [ django.contrib.admin, django.contrib.auth, django.contrib.contenttypes, django.contrib.sessions, django.contrib.messages, django.contrib.staticfiles, ] ROOT_URLCONF meiduo_mall.urls DATABASES { default: { ENGINE: django.db.backends.sqlite3, NAME: BASE_DIR / db.sqlite3, } } AUTH_USER_MODEL users.User上面这个配置的含义是数据库采用SQLite数据库文件名直接拼在项目根目录下URL配置入口是meiduo_mall.urls用户模型使用users这个app下的User。要注意AUTH_USER_MODEL一旦确定再想改回内置的auth.User就非常麻烦必须删库重新迁移因为所有与用户外键关联的表都会指向用户模型的完整路径。因此如果源码里已经有db.sqlite3你要先确认它使用的用户模型和settings里是否一致不一致时直接运行runserver会在访问用户表时报“no such table”。遇到这种情况我的处理方法是备份db.sqlite3后重新makemigrations和migrate。3. 美多商城的模型表结构与ORM查询实战3.1 用sqlite3导出表结构拿到db.sqlite3后可以用sqlite3命令或者Python内置的sqlite3模块快速查看数据库里已经存在的表。Django在migrate后会创建一组以app名字为前缀的表比如auth_user、goods_sku、order_order_info。先不要被表数量吓到只需要关注项目业务相关的表就能理解美多商城的核心关系。sqlite3 db.sqlite3 .tables执行结果会列出所有表名。如果系统里没有安装sqlite3命令也可以改用Python脚本import sqlite3 conn sqlite3.connect(db.sqlite3) cursor conn.cursor() cursor.execute(SELECT name FROM sqlite_master WHERE typetable) for row in cursor.fetchall(): print(row[0]) conn.close()这段代码利用SQLite系统表sqlite_master查询所有表名适合在没有命令行工具的Windows环境下快速核对数据库结构。参数说明db.sqlite3是项目根目录下的数据库文件如果连接时报“unable to open database file”先确认当前工作目录是否在manage.py同层。为了讲清楚模型之间的对应关系我把课程项目中常见的表结构和用途整理成下表表名对应模型主要用途关键字段users_userUser自定义用户表id, username, password, phoneauth_groupGroup用户分组id, namegoods_goodsGoods商品SPUid, name, subtitle, category_idgoods_skuSKU商品SKUid, goods_id, name, price, stockorder_order_infoOrderInfo订单主体id, order_sn, user_id, total_amount, statusorder_order_goodsOrderGoods订单商品明细id, order_id, sku_id, count, price从表结构可以看出商品SPU和SKU是典型的一对多关系订单和订单商品明细也是一对多用户和订单是外键关联。这里字段名后的_id表示Django外键在数据库层的默认列名ORM里的sku_id和数据库里的sku_id并不完全等价后者自动加了下划线。3.2 用ORM替代复杂SQL的多表查询很多做Java或PHP的人习惯手写SQL而Django的开发范式是直接通过模型管理器链式调用。下面这段代码演示的是查询库存低于10件的SKU以及当前用户最近10个订单及其商品明细。# 查询所有库存小于10的商品SKU from meiduo_mall.apps.goods.models import SKU skus SKU.objects.filter(stock__lt10) for sku in skus: print(sku.id, sku.name, sku.price, sku.stock) # 查询当前用户的订单并预加载明细避免N1 from meiduo_mall.apps.order.models import OrderInfo orders (OrderInfo.objects .filter(userrequest.user) .order_by(-create_time) .prefetch_related(ordergoods_set)[:10]) for order in orders: print(order.order_sn, order.total_amount) for item in order.ordergoods_set.all(): print(item.sku.name, item.count)这里需要注意filter里面的stock__lt10表示stock小于10双下划线是Django ORM的字段名和查询条件之间的连接符。prefetch_related的作用是提前查询关联的order_goods记录避免循环中逐条访问外键造成N1查询。如果这里不写prefetch_related打印订单明细时每条订单都会额外执行一次SQL订单量上来后性能会明显变差。另一个常见误用是习惯使用objects.raw()直接写SQL。虽然Django允许raw方式执行原生SQL但会在模型关系维护和跨数据库兼容性上埋坑。除非遇到复杂报表查询否则优先使用ORM的annotate和aggregate。3.3 admin后台快速验证数据美多商城项目通常已经配置了admin站点创建一个超级用户可以立刻进入后台查看商品和订单数据python manage.py createsuperuser python manage.py runserver然后在浏览器中访问/admin用刚才创建的账号登录。如果之前没有注册模型后台只有用户和分组两张表。要定制某个模型的后台展示可以在对应的admin.py中添加注册代码from django.contrib import admin from .models import SKU admin.register(SKU) class SKUAdmin(admin.ModelAdmin): list_display (id, name, price, stock, status) search_fields (name,) list_per_page 20这段代码把SKU模型的列表页展示为id、名称、价格、库存和状态字段并增加了名称搜索框每页显示20条。admin界面美化不一定要引入第三方组件先修改list_display和list_filter就能满足大多后台管理需求。4. 用户认证、购物车与订单状态机的代码落地4.1 Django认证系统与登录态美多商城的用户登录通常依赖Django内置的auth模块通过authenticate()校验用户名密码通过login()写入session。下面是一个视图函数中最简写法from django.contrib.auth import authenticate, login, logout from django.shortcuts import render, redirect def login_view(request): if request.method POST: username request.POST.get(username) password request.POST.get(password) user authenticate(request, usernameusername, passwordpassword) if user is not None: login(request, user) return redirect(/) return render(request, login.html, {error: 用户名或密码错误}) return render(request, login.html)这里authenticate的第一个参数传入request是Django 2.1之后推荐的写法目的是把request对象挂到user.backend上避免后续login时报“User authentication backends”错误。logout函数负责清掉当前session中的登录态。很多新手在登录失败时只会打印error却忘记把表单值也回填到模板用户体验不太好建议在render时把request.POST一并传给模板。如果要判断用户是否登录优先用request.user.is_authenticated它是一个几乎恒为布尔值的属性不是方法不能写成request.user.is_authenticated()。这个细节在课程作业答辩时经常被老师问到。4.2 购物车数据存在哪才合理美多商城是教学项目购物车实现方式有三种session、数据库表、Redis。压缩包配的是db.sqlite3最稳妥的改法是把购物车暂时存放在session中不侵入数据库表结构。session购物车本质是dict把SKU的ID作为key数量作为value。def add_to_cart(request, sku_id, count1): cart request.session.get(cart, {}) sku_id str(sku_id) if sku_id in cart: cart[sku_id] count else: cart[sku_id] count request.session[cart] cart request.session.modified True return cart这里的request.session.get(cart, {})表示从session中取出购物车字典如果不存在则返回空字典。为什么要把sku_id转成字符串因为session序列化到Cookie或缓存后数字类型的key在读写时可能发生类型不一致统一转成字符串最保险。request.session.modified True是强制标记session被修改否则某些session后端不会自动保存。这种实现方式逻辑简单但缺点是无法跨设备同步购物车。如果要升级成登录用户存储常见做法是另建一张Cart表外键关联User和SKU并在add视图里先判断用户是否登录未登录时写session登录后写数据库。处理同步的合并策略按商品ID聚合数量即可。4.3 订单创建事务与状态流转订单模块最容易暴露并发问题比如超卖和重复下单。课程项目一般不会直接上消息队列正确的做法是利用Django事务和行级锁。from django.db import transaction from django.db.models import F transaction.atomic def create_order(user, sku_id, buy_count): sku SKU.objects.select_for_update().get(idsku_id) if sku.stock buy_count: raise ValueError(库存不足) order OrderInfo.objects.create( useruser, order_sngenerate_order_sn(), total_amountsku.price * buy_count, statusUNPAID ) OrderGoods.objects.create( orderorder, skusku, countbuy_count, pricesku.price ) sku.stock F(stock) - buy_count sku.sales F(sales) buy_count sku.save(update_fields[stock, sales, update_time]) return orderselect_for_update()会对命中的SKU行加写锁直到事务结束才释放这样两个并发请求同时买同一个SKU时后一个请求会等待前一个事务完成再读取最新库存。使用F(stock) - buy_count是直接在数据库层面执行减操作比先读出stock再在Python里减一更安全避免读改写之间的竞态条件。订单状态字段status建议用固定字符串常量例如UNPAID、PAID、SEND、DONE、CANCEL不要在业务代码里到处写魔法值。可以从OrderInfo模型里定义class Status等枚举。事务回滚后订单表里不会留下半截数据这是django.db.transaction.atomic最直接的保障。5. 生产环境下的数据库切换、静态资源与部署优化5.1 从SQLite切到MySQL的配置调整开发环境用SQLite没问题一旦部署到服务器多进程并发写入会成为瓶颈所以生产环境一般切到MySQL。先安装客户端库pip install mysqlclient然后在settings.py中修改DATABASESDATABASES { default: { ENGINE: django.db.backends.mysql, NAME: meiduo, USER: root, PASSWORD: db_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: {charset: utf8mb4}, } }注意要把charset显式设为utf8mb4否则中文字符写入后可能出现乱码。执行migrate之前需要先在MySQL中创建meiduo数据库编码也要选utf8mb4。5.2 静态文件收集和gunicorn启动Django开发服务器不擅长处理静态文件生产上要把静态文件收集到统一目录让Nginx直接服务python manage.py collectstatic然后在Nginx配置里增加以下locationlocation /static/ { alias /var/www/meiduo/static/; expires 7d; }同时使用gunicorn启动后端服务gunicorn meiduo_mall.wsgi:application -w 4 -b 127.0.0.1:8000-w指定worker进程数一般为核心数x21。最后还要把settings.py里的DEBUG设为False并配置ALLOWED_HOSTS。将代码推上服务器后先看gunicorn日志里的ModuleNotFoundError那通常是虚拟环境没激活或者依赖没装全。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门