又到了课设、毕设集中开工的时间段,很多同学都在纠结选题:既要技术栈常见、资料好找,又要功能清晰、能写出东西,最好还能直接跑通、改一改就能交。如果你正在找这类项目,那基于Django + MySQL 的网购数据可视化分析系统是一个很稳的选择。这套系统在课程设计和毕业设计里出现频率很高,核心思路并不复杂:先做出网购数据的增删改查,再通过图表把统计结果展示出来。本文会从环境准备、数据库设计、核心代码到运行演示完整拆解,即使你之前只写过 Python 基础代码,也能一步步复现。项目源码可以继续在文末按说明获取,改改项目名称、换换数据集,就能变成一份自己的课设作品。
1. 项目背景与核心概念
1.1 什么是网购数据可视化分析系统
网购数据可视化分析系统,简单说就是:把电商业务中产生的订单、商品、用户、销售额等数据存到数据库里,然后通过 Web 页面展示统计分析结果。
这类系统通常包含两个层面:
- 数据管理层面:对商品信息、订单记录、用户信息进行维护,包括新增、修改、删除、查询。
- 数据可视化层面:对数据库中的记录做聚合统计,例如统计每月的销售额、各分类的商品数量、不同地区的订单分布,然后用折线图、柱状图、饼图展示出来。
从技术角度看,Django 负责业务逻辑和页面渲染,MySQL 负责数据存储,ECharts 负责图表绘制。三者结合后,系统能做到“录入数据 -> 保存到 MySQL -> 页面读取数据库 -> 生成可视化图表”的完整闭环。
1.2 为什么选择 Django 和 MySQL
Django 的优势
Django 是一个重量级的 Python Web 框架,内置了 ORM、Admin 后台、模板引擎、表单处理等能力。对课设和毕设来说,Django 最大的好处是“自带后台管理系统”,只要定义好数据模型,Django Admin 会自动生成一套可用的增删改查界面,省去大量重复的前端开发工作。
另外,Django 的 ORM 让开发者不用写原生 SQL 就能完成大部分数据库操作,这让代码的可读性和维护性都更好。
MySQL 的优势
MySQL 是使用最广泛的关系型数据库之一,在课程设计、毕业设计、企业开发中都很常见。网上关于 MySQL 的安装教程、问题排查资料非常多,遇到报错基本都能找到解决方案。Django 对 MySQL 的支持也非常成熟,通过mysqlclient或pymysql驱动即可连接。
可视化部分
可视化可以选用 ECharts 或 Chart.js。ECharts 在国内项目中使用更普遍,中文文档完善,图表类型丰富,做课设演示时视觉效果比较好。
1.3 系统适合的人群与应用场景
- 课程设计:适合 Python 方向课程、Web 开发课程、数据库课程。
- 毕业设计:适合计算机科学、软件工程、信息管理、电子商务等专业。
- 学习练手:适合想系统学习 Django + MySQL + 前后端数据交互的开发者。
这个项目的代码量适中,既不像纯登录注册那样单薄,也不像大型电商平台那样复杂,用来做课设或毕设的“骨架”非常合适。
2. 环境准备与版本说明
2.1 运行环境要求
本项目的运行环境可以归纳如下:
| 环境项 | 建议要求 |
|---|---|
| 操作系统 | Windows 10/11、macOS、Ubuntu 均可 |
| Python 版本 | Python 3.8 及以上 |
| Django 版本 | 本项目以 Django 3.x/4.x 为例,3.2 LTS 版本更稳 |
| MySQL 版本 | MySQL 5.7 或 8.0 |
| MySQL 驱动 | mysqlclient 或 pymysql |
| 前端可视化库 | ECharts(通过 CDN 引入即可) |
| IDE | PyCharm 或 VS Code |
这里特别说明一下:Django 版本迭代比较快,不同版本之间的配置方式有小差异。本文的代码和配置在 Django 3.2 / 4.x 下都能运行,如果你用的是 Django 5.x,需要注意urls.py的写法变化。
2.2 创建虚拟环境并安装 Django
为了不让项目依赖与系统全局 Python 环境冲突,建议先创建虚拟环境。
在项目目录下打开终端(Windows 使用 CMD 或 PowerShell,macOS/Linux 使用 Terminal):
# 创建虚拟环境 python -m venv venv # Windows 激活虚拟环境 venv\Scripts\activate # macOS/Linux 激活虚拟环境 source venv/bin/activate激活后,命令行前面会出现(venv)标识。接着安装 Django 和 MySQL 驱动。
以 Django 3.2 为例,可以指定版本安装:
pip install django==3.2.25 pip install mysqlclient如果你的环境安装mysqlclient失败,比如在 Windows 上缺少编译环境,可以改用pymysql:
pip install pymysql使用pymysql时,需要在项目的__init__.py文件中加入以下代码:
import pymysql pymysql.install_as_MySQLdb()2.3 创建 Django 项目和 App
虚拟环境准备就绪后,先创建项目和应用。假设项目名为online_shopping_analysis,应用名为analysis:
django-admin startproject online_shopping_analysis cd online_shopping_analysis python manage.py startapp analysis创建完成后,项目目录结构如下:
online_shopping_analysis/ ├── manage.py ├── online_shopping_analysis/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── analysis/ ├── __init__.py ├── admin.py ├── apps.py ├── models.py ├── views.py ├── migrations/ └── tests.py2.4 准备 MySQL 数据库
打开 MySQL,执行下面的 SQL 语句创建数据库:
CREATE DATABASE shopping_analysis CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;使用utf8mb4字符集很重要,它可以完整支持中文和特殊符号,避免页面出现乱码。
需要注意的是,数据库的用户名和密码要记住,后面配置 Django 连接时会用到。
3. 系统整体设计
3.1 功能模块划分
网购数据可视化分析系统可以拆分成以下几个功能模块:
| 功能模块 | 说明 |
|---|---|
| 用户管理模块 | 登录、注册、退出(可选) |
| 商品管理模块 | 商品分类、商品信息维护 |
| 订单管理模块 | 订单记录的新增、查询、删除 |
| 数据统计模块 | 销售额统计、订单量统计、商品分类占比 |
| 可视化展示模块 | 柱状图、折线图、饼图展示统计结果 |
对于课设和毕设来说,建议优先保证商品管理、订单管理、数据统计和可视化展示这四个模块,登录注册可以作为加分项。
3.2 数据库表结构设计
本项目可以设计以下三张核心数据表。
商品分类表 category
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 主键,自增 |
| name | varchar(50) | 分类名称 |
| create_time | datetime | 创建时间 |
商品表 product
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 主键,自增 |
| name | varchar(100) | 商品名称 |
| category | int | 外键,关联分类表 |
| price | decimal(10,2) | 商品单价 |
| stock | int | 库存数量 |
| sales | int | 销量 |
| create_time | datetime | 创建时间 |
订单表 order_info
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | int | 主键,自增 |
| order_no | varchar(50) | 订单编号 |
| product | int | 外键,关联商品表 |
| quantity | int | 购买数量 |
| total_price | decimal(10,2) | 订单总金额 |
| status | varchar(20) | 订单状态 |
| order_date | date | 下单日期 |
| create_time | datetime | 创建时间 |
3.3 项目目录结构说明
在实际开发中,建议把数据可视化相关代码放到analysis应用内,模板文件放在templates目录下,静态文件放在static目录下。完整结构如下:
online_shopping_analysis/ ├── manage.py ├── online_shopping_analysis/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── analysis/ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── views.py │ ├── tests.py │ └── migrations/ ├── templates/ │ ├── base.html │ ├── index.html │ ├── product_list.html │ └── chart.html └── static/ ├── css/ ├── js/ └── images/之所以单独建立templates和static目录,是为了让模板文件、静态资源与业务代码分离,后续维护和修改页面会方便很多。
4. 数据库配置与数据模型实现
4.1 Django 连接 MySQL 配置
打开online_shopping_analysis/settings.py,找到DATABASES配置项,修改为 MySQL 连接信息:
# 文件路径:online_shopping_analysis/settings.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'shopping_analysis', 'USER': 'root', 'PASSWORD': '你的数据库密码', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', }, } }这里有几个容易出错的地方:
NAME是数据库名称,必须先在 MySQL 中创建好。USER和PASSWORD要替换成自己的 MySQL 账号密码。HOST默认填127.0.0.1,如果 MySQL 部署在其他机器,要改成对应 IP。PORT默认是3306,如果你的 MySQL 端口被修改过,要同步修改。
同时,在settings.py中注册应用并配置模板目录:
# 文件路径:online_shopping_analysis/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'analysis', ] TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]如果使用pymysql驱动,还要在online_shopping_analysis/__init__.py中加入:
import pymysql pymysql.install_as_MySQLdb()4.2 编写数据模型
打开analysis/models.py,添加以下模型定义:
# 文件路径:analysis/models.py from django.db import models class Category(models.Model): """ 商品分类表 """ name = models.CharField(max_length=50, verbose_name='分类名称') create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') class Meta: verbose_name = '商品分类' verbose_name_plural = verbose_name db_table = 'category' def __str__(self): return self.name class Product(models.Model): """ 商品表 """ name = models.CharField(max_length=100, verbose_name='商品名称') category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name='商品分类') price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='商品单价') stock = models.IntegerField(default=0, verbose_name='库存数量') sales = models.IntegerField(default=0, verbose_name='销量') create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') class Meta: verbose_name = '商品信息' verbose_name_plural = verbose_name db_table = 'product' def __str__(self): return self.name class OrderInfo(models.Model): """ 订单表 """ order_no = models.CharField(max_length=50, verbose_name='订单编号') product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='商品') quantity = models.IntegerField(default=1, verbose_name='购买数量') total_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='订单总金额') status = models.CharField(max_length=20, verbose_name='订单状态') order_date = models.DateField(verbose_name='下单日期') create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') class Meta: verbose_name = '订单信息' verbose_name_plural = verbose_name db_table = 'order_info' def __str__(self): return self.order_no模型定义中有几个关键点:
ForeignKey表示外键关系,一个分类下可以有多个商品,一个商品可以有多条订单。on_delete=models.CASCADE表示分类或商品被删除时,关联数据也会同步删除。实际业务中也可以使用PROTECT防止误删。db_table用于指定数据库中的表名,不指定时 Django 会默认生成应用名_模型名形式的数据表。DecimalField适合存储价格,避免 Float 类型导致的精度问题。
4.3 注册后台管理
在analysis/admin.py中注册模型,方便通过 Django Admin 后台直接维护数据:
# 文件路径:analysis/admin.py from django.contrib import admin from .models import Category, Product, OrderInfo @admin.register(Category) class CategoryAdmin(admin.ModelAdmin): list_display = ('id', 'name', 'create_time') search_fields = ('name',) @admin.register(Product) class ProductAdmin(admin.ModelAdmin): list_display = ('id', 'name', 'category', 'price', 'stock', 'sales', 'create_time') list_filter = ('category',) search_fields = ('name',) @admin.register(OrderInfo) class OrderInfoAdmin(admin.ModelAdmin): list_display = ('id', 'order_no', 'product', 'quantity', 'total_price', 'status', 'order_date') list_filter = ('status',) search_fields = ('order_no',)4.4 生成迁移文件并同步数据库
定义好模型后,执行以下命令生成迁移文件并同步到 MySQL:
python manage.py makemigrations python manage.py migratemakemigrations会根据models.py中的变化生成迁移脚本,migrate会把迁移脚本真正执行到数据库中。
执行完成后,可以登录 MySQL 查看:
SHOW TABLES;正常情况下,应该能看到category、product、order_info这三张表以及 Django 自带的用户、权限等系统表。
5. 数据分析与可视化核心代码
5.1 使用 Django ORM 进行聚合统计
可视化图表需要的数据,不是原始表格数据,而是类似于“每个月的销售额是多少”“每个分类的商品数量是多少”这种统计结果。Django ORM 提供了annotate和values方法实现分组聚合。
下面是一个统计各商品分类商品数量的示例:
# 文件路径:analysis/views.py from django.db.models import Sum, Count from django.shortcuts import render from .models import Product, OrderInfo, Category def category_statistics(): """ 统计每个分类下的商品数量 """ categories = Category.objects.annotate(product_count=Count('product')) data = [] for category in categories: data.append({ 'name': category.name, 'value': category.product_count }) return data def sales_statistics(): """ 统计每个月的销售额 """ from django.db.models.functions import TruncMonth monthly_sales = ( OrderInfo.objects .annotate(month=TruncMonth('order_date')) .values('month') .annotate(total=Sum('total_price')) .order_by('month') ) months = [] totals = [] for item in monthly_sales: if item['month']: months.append(item['month'].strftime('%Y-%m')) totals.append(float(item['total'])) return months, totals其中,TruncMonth是 Django 提供的日期截断函数,可以把日期精确到月份,然后按月份分组求和。如果不需要用到这个函数,也可以先取出订单数据,在 Python 中手动分组,但效率会比数据库聚合差。
5.2 首页数据统计视图
编写一个视图函数,把统计数据传给模板:
# 文件路径:analysis/views.py from django.shortcuts import render from .models import OrderInfo, Product def index(request): """ 系统首页:展示核心指标和图表数据 """ total_orders = OrderInfo.objects.count() total_sales = OrderInfo.objects.aggregate(total=Sum('total_price'))['total'] or 0 total_products = Product.objects.count() # 获取近 30 天每日销售额 from django.utils import timezone from datetime import timedelta end_date = timezone.now().date() start_date = end_date - timedelta(days=29) daily_orders = ( OrderInfo.objects .filter(order_date__range=[start_date, end_date]) .values('order_date') .annotate(daily_total=Sum('total_price')) .order_by('order_date') ) date_list = [] sales_list = [] for item in daily_orders: date_list.append(item['order_date'].strftime('%m-%d')) sales_list.append(float(item['daily_total'])) context = { 'total_orders': total_orders, 'total_sales': round(total_sales, 2), 'total_products': total_products, 'date_list': date_list, 'sales_list': sales_list, 'category_data': category_statistics(), } return render(request, 'index.html', context)5.3 模板页面与 ECharts 图表展示
在templates目录下创建base.html,作为所有页面的基础模板:
<!-- 文件路径:templates/base.html --> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}网购数据可视化分析系统{% endblock %}</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"> {% block extra_css %}{% endblock %} </head> <body> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <div class="container"> <a class="navbar-brand" href="/">网购数据分析</a> <div class="collapse navbar-collapse"> <ul class="navbar-nav me-auto"> <li class="nav-item"><a class="nav-link" href="/">首页</a></li> <li class="nav-item"><a class="nav-link" href="/products/">商品管理</a></li> <li class="nav-item"><a class="nav-link" href="/admin/">后台管理</a></li> </ul> </div> </div> </nav> <div class="container mt-4"> {% block content %}{% endblock %} </div> <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script> {% block extra_js %}{% endblock %} </body> </html>创建templates/index.html,展示数据指标和两个统计图表:
<!-- 文件路径:templates/index.html --> {% extends 'base.html' %} {% block content %} <div class="row"> <div class="col-md-4"> <div class="card text-white bg-primary mb-3"> <div class="card-body"> <h5 class="card-title">商品总数</h5> <p class="card-text fs-3">{{ total_products }}</p> </div> </div> </div> <div class="col-md-4"> <div class="card text-white bg-success mb-3"> <div class="card-body"> <h5 class="card-title">订单总数</h5> <p class="card-text fs-3">{{ total_orders }}</p> </div> </div> </div> <div class="col-md-4"> <div class="card text-white bg-warning mb-3"> <div class="card-body"> <h5 class="card-title">总销售额</h5> <p class="card-text fs-3">¥{{ total_sales }}</p> </div> </div> </div> </div> <div class="row mt-4"> <div class="col-md-7"> <div class="card"> <div class="card-header">近30天销售额趋势</div> <div class="card-body"> <div id="salesChart" style="height: 350px;"></div> </div> </div> </div> <div class="col-md-5"> <div class="card"> <div class="card-header">商品分类占比</div> <div class="card-body"> <div id="categoryChart" style="height: 350px;"></div> </div> </div> </div> </div> {% endblock %} {% block extra_js %} <script> // 近30天销售额折线图 var salesChart = echarts.init(document.getElementById('salesChart')); var dateList = {{ date_list|safe }}; var salesList = {{ sales_list|safe }}; salesChart.setOption({ tooltip: { trigger: 'axis' }, xAxis: { type: 'category', data: dateList }, yAxis: { type: 'value' }, series: [{ name: '销售额', type: 'line', smooth: true, data: salesList, areaStyle: {} }] }); // 商品分类占比饼图 var categoryChart = echarts.init(document.getElementById('categoryChart')); var categoryData = {{ category_data|safe }}; categoryChart.setOption({ tooltip: { trigger: 'item' }, series: [{ name: '商品分类', type: 'pie', radius: '60%', data: categoryData }] }); </script> {% endblock %}这里使用|safe过滤器,是为了让 Django 模板不要转义数据中的引号和 HTML 符号。实际开发时,如果数据是动态传入的字符串,需要更谨慎地处理 XSS 风险。图表本身通过 ECharts 的 CDN 加载,不需要下载单独的 JS 文件。
5.4 配置 URL 路由
在online_shopping_analysis/urls.py中配置路由:
# 文件路径:online_shopping_analysis/urls.py from django.contrib import admin from django.urls import path from analysis import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index, name='index'), ]如果后续添加商品列表页面、订单列表页面,也可以在同一个urls.py中继续扩展:
path('products/', views.product_list, name='product_list'), path('orders/', views.order_list, name='order_list'),6. 系统运行与验证
6.1 创建超级管理员账号
Django Admin 后台需要管理员账号才能登录。执行以下命令:
python manage.py createsuperuser按提示输入用户名、邮箱(可留空)和密码即可。
6.2 准备演示数据
为了让可视化图表有内容可展示,需要先录入一些数据。有两种方式:
方式一:通过 Django Admin 后台录入
启动服务后访问http://127.0.0.1:8000/admin/,登录后进入“商品分类”“商品信息”“订单信息”页面手动添加数据。
方式二:编写数据初始化脚本
在analysis应用下创建init_data.py脚本,一次性写入模拟数据:
# 文件路径:analysis/init_data.py import os import django from datetime import date, timedelta import random os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'online_shopping_analysis.settings') django.setup() from analysis.models import Category, Product, OrderInfo def init_data(): # 创建分类 categories = ['手机数码', '家用电器', '服饰鞋包', '食品生鲜', '美妆护肤'] category_objs = [] for cate in categories: obj, created = Category.objects.get_or_create(name=cate) category_objs.append(obj) # 创建商品 product_names = { '手机数码': ['智能手机', '蓝牙耳机', '智能手表', '平板电脑'], '家用电器': ['空气炸锅', '扫地机器人', '电饭煲', '破壁机'], '服饰鞋包': ['运动鞋', '双肩包', '卫衣', '休闲裤'], '食品生鲜': ['车厘子', '坚果礼盒', '有机牛奶', '牛排套餐'], '美妆护肤': ['保湿面霜', '精华液', '口红', '防晒霜'], } products = [] for cate in category_objs: names = product_names[cate.name] for name in names: product = Product.objects.create( name=name, category=cate, price=random.uniform(50, 5000), stock=random.randint(10, 500), sales=random.randint(0, 1000), ) products.append(product) # 创建订单 for i in range(200): product = random.choice(products) quantity = random.randint(1, 5) order_date = date.today() - timedelta(days=random.randint(0, 30)) OrderInfo.objects.create( order_no=f'NO2024{i+1:06d}', product=product, quantity=quantity, total_price=product.price * quantity, status=random.choice(['已完成', '待发货', '已取消']), order_date=order_date, ) print('数据初始化完成') if __name__ == '__main__': init_data()执行脚本:
python analysis/init_data.py注意:这个脚本只是演示用的数据初始化方式,不是项目必需的模块。如果你不希望保留它,录入完数据后可以直接删除。
6.3 启动服务
在项目根目录执行:
python manage.py runserver看到以下输出说明启动成功:
Starting development server at http://127.0.0.1:8000/访问http://127.0.0.1:8000/可以看到首页的数据卡片和图表。访问http://127.0.0.1:8000/admin/可以进入后台管理数据。
7. 常见问题与排查思路
在配置和运行 Django + MySQL 项目时,大家比较容易遇到下面几类问题。我整理了一张排查表,帮助快速定位错误。
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
ModuleNotFoundError: No module named 'MySQLdb' | 未安装 MySQL 驱动或 pymysql 未生效 | 安装 mysqlclient,或使用 pymysql 并执行pymysql.install_as_MySQLdb() |
django.db.utils.OperationalError: (1045, "Access denied for user...") | MySQL 用户名或密码错误 | 检查 settings.py 数据库配置,确认账号密码和权限 |
django.db.utils.OperationalError: (1049, "Unknown database") | 数据库未创建 | 先在 MySQL 中创建数据库,再执行 migrate |
| 中文乱码 | 数据库字符集不是 utf8mb4 | 建库时指定CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci |
Error: Port 8000 is already in use | 8000 端口被占用 | 换端口启动:python manage.py runserver 8080 |
Table 'xxx' already exists | 迁移记录与数据库不一致 | 谨慎处理,备份后可通过python manage.py migrate --fake解决,不熟悉时优先咨询 |
| 页面图表不显示 | JS 加载失败或数据格式不对 | 打开浏览器开发者工具,检查 Console 报错和接口返回的数据格式 |
7.1 数据库连接失败
如果你看到类似django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on '127.0.0.1'")的报错,可以按顺序排查:
- 检查 MySQL 服务是否启动。Windows 可以在服务管理器中查看 MySQL 服务状态。
- 检查
settings.py中的HOST和PORT是否写对。 - 使用 Navicat 或命令行尝试连接 MySQL,确认账号密码可用。
- 如果 MySQL 版本是 8.0,确认密码认证插件是否为
caching_sha2_password,部分旧版本驱动可能不兼容,需要更新驱动版本或修改认证方式。
7.2 迁移命令报错
如果执行python manage.py migrate时报错,可以先检查INSTALLED_APPS中是否已经注册了analysis应用。
另外,如果改过models.py后报出字段缺失、字段类型不匹配等错误,不要直接去数据库手动改表。正确做法是:备份好数据库,删除对应应用migrations目录中最近生成的迁移文件,重新执行makemigrations和migrate。如果数据库中已经有重要数据,这个操作会带来数据丢失风险,务必先做备份。
7.3 图表区域空白
图表空白通常有下面几种原因:
- ECharts 的 CDN 资源加载失败。可以检查网络连接,或把
echarts.min.js下载到本地static/js目录。 - 容器
div没有高度。ECharts 初始化前必须保证容器有明确的宽度和高度,如果容器高度为 0,图表会渲染不出来。 - JavaScript 数据格式不对。比如
date_list传到模板后变成了字符串,可以在模板中输出查看,必要时使用|safe过滤器。
8. 课设/毕设写作与答辩建议
8.1 课程设计报告结构
如果这是你的课程设计或毕业设计,报告结构可以参考下面的通用模板:
| 章节 | 内容建议 |
|---|---|
| 第1章 绪论 | 项目背景、研究意义、国内外现状 |
| 第2章 相关技术介绍 | Python、Django、MySQL、ECharts 简介 |
| 第3章 系统分析 | 可行性分析、功能需求分析、用例图 |
| 第4章 系统设计 | 总体架构、数据库表结构、页面设计 |
| 第5章 系统实现 | 核心代码、关键功能截图、运行效果 |
| 第6章 系统测试 | 测试环境、测试用例、测试结果 |
| 第7章 总结与展望 | 项目总结、不足与改进方向 |
写报告时最容易犯的错误是“技术介绍占了一半,核心实现只有两页”。建议把重点放在系统设计和系统实现部分,用截图 + 代码片段说明你做了什么、解决了什么问题。
8.2 答辩时需要准备的内容
答辩时,评委通常会关注以下几点:
- 系统是否真的能跑起来,演示过程是否流畅。
- 数据库表结构是否合理,为什么这样设计。
- 用到了哪些 Django 核心功能,ORM 的聚合查询是否理解。
- 图表的数据是怎么传递的,前端如何拿到后端数据。
- 项目有哪些可以优化的地方。
所以建议在答辩前准备好几份演示数据,把页面图表效果调到比较饱满的状态。同时,把项目跑通后,再自己走一遍“新增商品 -> 新增订单 -> 首页图表变化”的流程,这样回答“数据怎么影响图表”时会更从容。
8.3 代码二次开发建议
如果你拿到的源码项目名、类名和你的课程题目不完全一致,可以进行以下简单的定制:
- 修改项目名称和 App 名称。
- 修改
templates中的标题、导航栏、页面文案。 - 替换数据集或模拟数据。
- 增加新的统计维度,比如按地区统计、按年龄段统计。
- 增加导出 Excel 报表功能。
- 引入用户登录注册功能,区分普通用户和管理员。
修改项目名称时,除了目录名,还需要同步修改settings.py中的ROOT_URLCONF、WSGI_APPLICATION等配置项中的模块路径。建议全局搜索旧名称,逐一替换。
8.4 工程实践建议
这里再强调几条工程实践层面的建议,不只是为了应付课设,对你以后写项目也有帮助。
配置与代码分离
不要在生产环境代码里直接写死数据库密码。课设阶段问题不大,但如果有条件,可以使用环境变量或config.py文件统一管理敏感配置。例如:
import os DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': os.getenv('DB_NAME', 'shopping_analysis'), 'USER': os.getenv('DB_USER', 'root'), 'PASSWORD': os.getenv('DB_PASSWORD', ''), 'HOST': os.getenv('DB_HOST', '127.0.0.1'), 'PORT': os.getenv('DB_PORT', '3306'), } }备份数据库
涉及数据库修改、模型迁移前,先备份数据库:
mysqldump -u root -p shopping_analysis > shopping_analysis_backup.sql恢复时可以执行:
mysql -u root -p shopping_analysis < shopping_analysis_backup.sql迁移操作前谨慎
Django 的迁移命令是项目中最容易出问题的环节之一。每次改动模型前,先想清楚字段变化的影响范围。如果是在已经提交过的项目中操作,不要随意删除旧迁移文件。
合理处理异常
写视图函数时,尽量在不同场景下给用户明确反馈。比如找不到商品时返回 404,参数不合法时返回提示信息。Django 内置的get_object_or_404、Http404就很常用。
from django.shortcuts import get_object_or_404, render from .models import Product def product_detail(request, pk): product = get_object_or_404(Product, pk=pk) return render(request, 'product_detail.html', {'product': product})9. 总结与下一步学习方向
本文从一个课设/毕设常见的需求出发,完整拆解了Django 网购数据可视化分析系统的设计与实现过程。你跟着文章走一遍,可以掌握这些内容:
- 使用 Django 创建项目和 App,配置连接 MySQL。
- 通过 ORM 定义分类、商品、订单三张核心数据表。
- 使用 Django Admin 后台快速完成数据维护。
- 使用聚合查询和 ECharts 展示统计图表。
- 配置路由和模板,完成前后端数据传递。
如果你之前没有接触过 Django,建议在跑通这个系统后,再手动写一遍代码,不要直接复制粘贴完就结束。把models.py的每个字段、views.py的每个查询、模板里的每个模板标签都理解透彻,答辩时才会心中有数。
接下来可以继续深入的方向包括:
- 学习 Django 的用户认证系统,把这套系统扩展成带登录注册的完整平台。
- 学习 Django REST Framework,把这套数据统计分析能力做成 API 接口。
- 学习 Pandas 和 Matplotlib,对比 Python 数据分析和 Web 可视化的差异。
- 学习 MySQL 索引优化,思考订单量变大时如何提升查询速度。
如果这篇文章对你有帮助,建议收藏备用,动手实践时遇到的问题也欢迎在评论区交流。