基于Python的食品营养特征数据可视化分析系统 毕业论文

毕业设计


一、项目名称:

基于Python的食品营养特征数据可视化分析系统


【摘要】

食品营养数据分散在 CSV 与成分表中,公众与教学场景难以快速完成分类分布、营养素对比、营养密度评估与多维挖掘。本文设计并实现了基于 Python 与 Django 的食品营养特征数据可视化分析系统,面向毕业设计与营养数据教学演示,将中国食物成分表样本清洗入库后,以交互式图表支撑多维营养分析与算法辅助解读。

系统采用 B/S 架构,后端基于 Django 3.1,管理端集成 SimpleUI;数据库使用 MySQL(库名 nutrition),通过 PyMySQL 驱动接入。前台基于 Bootstrap 5 模板、nutrition-theme.css 营养主题与 ECharts 5 完成可视化。业务核心表为 FoodRecord(约 1657 条),字段涵盖食品名称、中国食物成分表分类、热量及 26 维营养素;前台用户由自建 User 表维护。数据经 scripts/fetch_china_food_data.py 同步中国食物成分表(备选 fetch_usda_food_data.py),再由 manage.py import_foods 批量导入。分析层在 app/utils/nutrition_charts.py 中以 pandas 聚合,配合 nutrition_core.py 缓存 bundle API。算法侧实现 Spearman 秩相关热力图、Kruskal-Wallis 分类差异检验、NDI 营养密度指数、GMM 高斯混合聚类、PCA 二维投影、综合健康评分与 1.5×IQR 异常检测;不包含 Pearson 相关、WMA 预测、协同过滤等与本数据集无关的能力。系统入口为 manage.py,运行端口 8000;前台登录路径 /app/login/(账号 admin/123456),登录后进入 /app/home/;后台为 Django 超管 SimpleUI /admin/admin/admin123)。中间件 AuthMiddleware 对未登录访问拦截,豁免 /app/login//app/register//admin/ 前缀。

测试与运行结果表明,系统能够完成登录鉴权、食品列表筛选导出、基础分析、统计检验、营养密度、聚类挖掘、SimpleUI 后台维护与缓存刷新等闭环,界面清晰、响应稳定,可为食品营养数据分析课题研究与教学演示提供可用支撑。

【关键词】 Django;食品营养;数据可视化;ECharts;Spearman相关

【Abstract】

Food nutrition data is often scattered across CSV files and composition tables, making unified aggregation and visualization difficult for teaching and public health education. This thesis designs and implements a Python- and Django-based food nutrition feature data visualization and analysis system. China Food Composition Table samples are cleaned, imported and explored through interactive charts.

The system follows a B/S architecture. The backend uses Django 3.1 with SimpleUI; MySQL database name is nutrition. The frontend adopts Bootstrap 5, nutrition theme and ECharts 5. Core table FoodRecord holds about 1657 rows with food name, China Food Composition Table categories and 26 nutrient dimensions. Data is synced primarily by fetch_china_food_data.py (optional fetch_usda_food_data.py) and imported by import_foods. Analysis uses pandas aggregation in nutrition_charts.py with cached bundle APIs in nutrition_core.py. Algorithms include Spearman rank correlation, Kruskal-Wallis test, NDI nutrient density index, GMM clustering, PCA projection, composite health score and 1.5×IQR anomaly detection. No Pearson correlation, WMA forecast or collaborative filtering. Entry point is manage.py, port 8000; frontend login /app/login/ (admin/123456) to /app/home/; admin /admin/ (admin/admin123). AuthMiddleware exempts login, register and admin paths.

Results show that authentication, food list/export, basic analysis, statistical tests, nutrient density, clustering/mining pages, SimpleUI admin and cache invalidation work stably for course demos.

【Keywords】 Django; Food Nutrition; Data Visualization; ECharts; Spearman Correlation


目 录

1 绪 论

2 相关技术

3 系统分析与设计

4 系统实现

5 系统测试

6 总结与展望

参考文献

致谢


1 绪 论

1.1 课题研究背景

居民膳食结构与慢性病防控日益受到关注,食品营养数据库通常包含食品名称、分类、热量、宏量营养素与维生素矿物质等字段。教学与公众科普场景常见需求包括:汇总各分类食品数量与平均热量、对比蛋白质/脂肪/碳水分布、评估同等热量下的营养密度、识别营养素之间的关联模式,并对食品进行聚类分组与健康评分排序。当样本规模达到千级且字段维度达到 26 维时,若每次分析都在应用层重复全表加载且缺乏可视化,将导致响应变慢、讲解成本上升,难以在毕业设计答辩环境中稳定演示。

在高校毕业设计与营养数据教学演示场景中,常见需求包括:一是需要一套可本地部署的系统,用统一库表承载约 1657 条中国食物成分表样本;二是需要按营养分析维度拆分 Web 页面,以 ECharts 完成筛选、对比与下钻;三是需要可讲解的统计与轻量挖掘算法(Spearman 相关、Kruskal-Wallis 检验、NDI 营养密度、GMM 聚类、PCA 降维、健康评分、IQR 异常检测),并明确算法边界,避免虚构与本项目字段无关的推荐或预测能力。基于上述背景,本课题以 Django 为主框架,构建食品营养特征数据可视化分析系统:数据以中国食物成分表 CSV 为主,前台 ECharts 负责展示,SimpleUI 后台负责食品与用户维护。系统默认端口 8000;分析层通过 pandas 聚合与 LocMemCache 缓存 bundle,便于在千级样本下保持秒级响应。

1.2 课题研究的目的、意义

1.2.1 研究目的

本课题的主要目的包括:

  1. 建立以 FoodRecordUser 为核心的数据模型,覆盖 26 维营养素字段与中国食物成分表分类,支撑统一查询与多维聚合。
  2. 实现前台会话登录、侧栏导航与多分析页展示,服务端口为 8000,登录路径 /app/login/,首页 /app/home/,后台 /admin/
  3. 基于 nutrition_charts.py 与 Django ORM 完成统计分析,前端通过 bundle API 与 ECharts 渲染。
  4. 通过 fetch_china_food_data.pyimport_foods 完成 CSV 同步与批量入库;提供 Spearman 相关、Kruskal-Wallis 检验、NDI 营养密度、GMM 聚类、PCA 投影、健康评分与 IQR 异常检测。
  5. 输出可运行、可演示的完整系统,默认前台账号 admin/123456、后台 admin/admin123,便于验收与二次扩展。
1.2.2 研究意义

理论意义:将 Web 开发、关系型存储与轻量统计算法结合到统一课题中,形成「CSV 入库—pandas 聚合—缓存 bundle—图表页—算法说明」的可复用范式,有助于理解千级多维营养样本下「缓存 DataFrame + 按需 bundle」的工程取舍。

实践意义:系统把约 1657 条食品记录、前台用户与 Django 超管分层管理,降低手工处理成本;分析页按营养维度拆分路由,便于逐模块讲解;算法代码路径清晰,便于核对结果与答辩演示。

社会意义:可视化结果有助于直观认识不同食品分类的营养结构差异、营养密度排行与健康评分分布,提升学生对公开营养数据可用性的认识。

经济意义:本地化部署与开源技术栈降低课题演示成本;模块化 bundle 与路由设计便于后续替换数据源或扩展指标,减少重复开发投入。

1.3 课题的国内外研究现状和发展动态

1.3.1 国外研究现状

国外营养数据库建设起步较早,美国 USDA FoodData Central 提供 SR Legacy 等公开数据集,涵盖 18 类食品分组与详细营养素字段。统计领域常用 Spearman 秩相关分析非正态营养素关联;Kruskal-Wallis 检验用于多组分类间差异;营养密度(NDI)用于衡量单位热量下的营养素含量;聚类方面 GMM 与 PCA 常用于高维营养特征降维与分组。可视化方面,ECharts、D3.js 等库被用于交互式统计图。本课题在教学场景下选用 Spearman + Kruskal-Wallis + NDI + GMM/PCA + 健康评分 + IQR 异常检测,并明确不引入与本数据集字段无关的协同过滤推荐。

1.3.2 国内研究现状

国内《中国食物成分表》及开源整理项目为高校毕设提供了可复现样本。部分系统侧重大屏态势,部分侧重 CRUD 与简单图表。本课题更强调「六大功能模块 + 按营养维度拆分分析页 + 中国食物成分表真实数据 + SimpleUI 后台 + bundle API 缓存」,并以 MySQL 持久化食品记录,兼顾可解释统计与可复现部署。

1.3.3 发展趋势

未来营养数据分析将更强调多维下钻、营养密度评估与可解释挖掘。可视化从静态报表走向可筛选、可联动的交互分析;后端则更注重索引、DataFrame 缓存与版本控制。对本系统而言,后续可扩展更稳健的密码哈希与更精细的聚类参数调优,但仍应保持教学场景下结构清晰、部署简单的特点。

1.4 研究内容

本课题主要研究内容如下:

  1. 数据采集与入库:设计面向中国食物成分表 CSV 的同步与导入流程,支持 fetch_china_food_data.py 落盘与 import_foods --truncate 批量写入 FoodRecord
  2. 用户与权限:实现自建用户表注册登录、会话保持与中间件拦截;Django 超管与前台用户分离。
  3. 食品数据管理:实现食品列表分页筛选、统计卡片与 CSV 导出;后台维护食品营养记录。
  4. 基础分析:实现分类饼图、营养素箱线图、宏量营养素对比与热量分布等基础图表页。
  5. 统计与密度分析:实现 Spearman 相关热力图、Kruskal-Wallis 检验、雷达对比、NDI 热力图与 Top 排行。
  6. 聚类与挖掘:实现 GMM 聚类、PCA 二维投影、综合健康评分与 IQR 异常检测。
  7. SimpleUI 后台:实现 /admin/ 下食品记录与用户 CRUD、分类筛选与搜索。

1.5 论文结构安排

第 1 章绪论,说明背景、目的意义、研究现状与研究内容。第 2 章介绍 Python、Django、MySQL、ECharts、统计算法及相关技术特色。第 3 章给出系统架构、数据流、六大模块详细设计与数据库关系。第 4 章按模块说明实现流程、核心代码、访问路径与界面效果。第 5 章给出功能测试用例与性能测试分析。第 6 章总结工作并展望后续方向。文末附参考文献与致谢。


2 相关技术

2.1 Python编程语言

Python 具备清晰语法与丰富第三方库,适合 Web 后端与数据处理。本系统使用 Python 3.11 环境,依赖 requirements.txt 中的 Django 3.1.14、pandas 2.3、numpy 2.3、scipy 1.16、scikit-learn 1.7、PyMySQL、django-simpleui 等。导入脚本与 bundle 聚合使用标准库 csvhashlib;算法侧在相关、检验、聚类 bundle 中使用 scipy.stats 与 sklearn;分析 DataFrame 经 cached_analysis_df 按筛选条件缓存。

2.1.1 数据处理与脚本组织

项目将数据同步独立于 scripts/fetch_china_food_data.pyscripts/fetch_usda_food_data.py,导入命令位于 app/management/commands/import_foods.py,与业务视图 app/views.py、工具模块 app/utils/nutrition_*.py 解耦。

2.1.2 与 Django 的协作方式

业务入口为 manage.py,配置集中在 基于Django系统/settings.py。视图层负责页面渲染与导出接口,API 层 api_views.py 统一返回 JSON bundle;模型层映射 MySQL 表,模板层使用 Bootstrap 5 与 nutrition-theme.css 布局。

2.2 Django Web框架

Django 采用 MTV(Model-Template-View)组织方式。本系统 Django 版本为 3.1.14,应用名为 app,根路由在 基于Django系统/urls.py 挂载 /app//admin/

2.2.1 MTV模式与路由组织

模型定义于 app/models.py;页面视图集中在 views.py;模板分布在 templates/app/templates/app/urls.py 按认证、分析模块、食品列表、API bundle 分组注册路径,统一前缀为 /app/

2.2.2 会话与中间件

INSTALLED_APPS 包含 simpleuiapp 等。中间件链注册 middleware.auth.AuthMiddleware:未登录访问非豁免路径时重定向至 /app/login/。前台登录态以 session['username'] 标识;后台使用 Django 内置 auth_user 超管,与前台 User 表分离。

2.3 MySQL数据库

业务库名为 nutrition,连接配置于 settings.py(默认 localhost:3306,用户 root,密码 123456,字符集 utf8mb4)。引擎为 django.db.backends.mysql

2.3.1 ORM与索引设计

FoodRecordfood_namecategory_name 建立索引,复合索引 idx_food_category 支撑分类与名称联合查询。列表与分析大量使用 filter、聚合与分页。

2.3.2 初始化数据

课题演示以中国食物成分表 CSV(1657 条)导入为主。执行 python manage.py seed_admin 可创建前台用户 admin/123456 与 Django 超管 admin/admin123

2.4 ECharts可视化技术

前台分析页通过 static/js/nutrition_pages.jschart_helpers.js 调用 bundle API,用 ECharts 5 渲染饼图、箱线图、热力图、雷达图、散点图等。各模块页共享分类/关键字筛选条;主题色由 nutrition-theme.css 定义营养绿风格侧栏。

2.5 统计分析算法

Spearman 秩相关矩阵stat_bundle 对 26 维 NUTRIENT_FIELDS 计算 Spearman 相关系数,输出热力图;不等于因果推断,页面附带算法说明文案。

Kruskal-Wallis 检验:按食品分类分组,对选定营养素执行非参数差异检验;p < 0.05 表示组间分布差异显著,不要求正态分布。

NDI 营养密度指数compute_ndi 计算 NDI =(营养素含量 ÷ 热量)× 100,衡量同等热量下的营养素「划算度」;热力图按分类与营养素取均值,Top 排行取前 15 名食品。

GMM 聚类与 PCA 降维:对 26 维营养素标准化后,默认 4 簇 GMM 分组(可配置 2~6 簇),PCA 压缩为 PC1、PC2 二维散点,颜色对应聚类标签。

综合健康评分health_score 对纤维、蛋白、维生素 C、钙、铁等加分,对钠、饱和脂肪、糖等减分,min-max 归一化后加权映射到 0~100 分。

IQR 异常检测_iqr_anomaliesQ1−1.5×IQRQ3+1.5×IQR 确定阈值,找出某营养素明显偏离大多数食品的样本,默认字段为钠。

2.6 技术特色与创新点

算法方面:相关分析采用 Spearman 秩相关,适合非正态营养数据;NDI 与 health_score 提供可解释的营养评价指标;GMM + PCA 组合展示高维营养结构;虚构 Pearson 相关、WMA 预测或协同过滤推荐。

数据处理方面:千级样本经 cached_analysis_df 缓存 DataFrame;bundle 结果经 LocMemCache 与版本号 nutrition:cache_version 缓存;聚类结果单独缓存以控制计算开销。

可视化特色:分析维度与营养字段一一对应;侧栏覆盖仪表盘、基础分析、统计、密度、聚类、挖掘与食品列表;营养主题统一品牌感。

架构优势:页面视图与 bundle API 分离,前端并行请求多图表;SimpleUI 后台与前台 Session 分离。

体验方面:食品列表支持分类/关键字筛选与每页 20 条分页;导出 UTF-8 BOM CSV;课题演示以 8000 端口本地运行为准。


3 系统分析与设计

3.1 系统总体设计

3.1.1 系统架构设计

系统采用经典三层 B/S 结构:表现层为登录注册页、首页仪表盘、各分析模板、食品列表与 SimpleUI 后台;业务层包含会话认证、pandas 聚合、bundle 缓存、统计算法与 CSV 导出;数据层为 MySQL nutrition 库及 food_nutrition_data.csv。浏览器通过 HTTP 访问 8000 端口,Django 处理页面与 API 请求,聚合与算法在服务端完成后以 JSON 驱动 ECharts 渲染。

图3.1 系统架构图

数据访问层

业务逻辑层

表现层

登录/注册页

数据仪表盘首页

基础分析页

统计与密度页

聚类与挖掘页

食品列表与导出

SimpleUI后台

AuthMiddleware 会话认证

views 页面视图

api_views bundle接口

nutrition_charts 数据聚合

nutrition_core 缓存与筛选

Spearman/KW/NDI/GMM/PCA/健康评分/IQR

CSV导出

MySQL: nutrition

食物成分 CSV

fetch/import_foods

3.1.2 系统数据流设计

从外部看,前台用户提交账号口令进入系统,管理员通过 SimpleUI 维护食品与用户,中国食物成分表 CSV 向导入脚本提供数据源。系统内部完成鉴权、筛选聚合、图表 bundle、算法计算与入库。

图3.2 顶层数据流图

账号/筛选/分析请求

CRUD操作

food_nutrition_data.csv

页面与图表JSON

管理反馈

同步落盘

业务记录

前台用户

食品营养特征数据可视化分析系统

后台管理员

外部数据源
中国食物成分表 CSV

data/raw 目录

MySQL nutrition

图3.3 0层数据流图

前台用户

1.0 用户认证

2.0 食品数据管理

3.0 基础分析

4.0 统计与密度

5.0 聚类与挖掘

管理员

6.0 SimpleUI后台

运维/初始化

7.0 CSV导入与启动

User表

FoodRecord表

图表bundle输出

3.1.3 系统功能模块设计

结合侧栏实际菜单与路由划分,系统功能划分为六大模块:(1)用户认证;(2)食品数据管理(列表/导出/后台);(3)基础分析;(4)统计与密度(Spearman/Kruskal-Wallis/雷达 + NDI);(5)聚类与挖掘(GMM/PCA + 健康评分/IQR);(6)SimpleUI 后台。各模块对应独立页面路由与 bundle API;个人信息与改密挂载于认证模块延伸功能。

图3.4 系统功能结构图

食品营养特征数据可视化分析系统

用户认证

食品数据管理

基础分析

统计与密度

聚类与挖掘

SimpleUI后台

登录注册退出

个人资料与改密

食品列表分页筛选

CSV导出

后台食品维护

分类饼图

营养素箱线图

宏量营养素对比

Spearman相关热力图

Kruskal-Wallis检验

雷达对比与NDI热力图

GMM聚类与PCA投影

健康评分排行

IQR异常检测

FoodRecord CRUD

User CRUD

3.2 系统详细设计

3.2.1 用户认证模块设计

模块负责前台注册、登录、退出及会话保持,以及个人资料、头像与密码修改。用户信息存储于自定义 User 表;登录成功后将 username 写入 request.session。中间件 AuthMiddleware 对未登录访问重定向至 /app/login/,豁免 /app/login//app/register/ 与以 /admin/ 开头的后台路径。前台演示账号为 admin/123456(明文密码校验);Django 超管通过 seed_admin 创建,密码 admin123,与前台用户表分离。

3.2.1.1 用户认证流程设计

图3.5 用户认证模块流程图

GET

POST

匹配

不匹配

通过

失败

访问 /app/login/

请求方法

渲染 login.html

读取用户名密码

User表明文校验

写入 session username

跳转 /app/home/

提示用户名或密码错误

访问 /app/register/

注册校验

创建 User 记录

跳转登录页

提示空值/重复/密码不一致

访问受保护页

session.username?

放行视图

3.2.2 食品数据管理模块设计

模块提供食品列表 /app/food_list/、CSV 导出 /app/api/export/ 与 SimpleUI 后台食品维护。列表支持按分类、关键字筛选,分页每页 20 条,展示食品名称、分类、热量、蛋白、脂肪、碳水等字段。导出按当前筛选条件输出 UTF-8 BOM CSV。

3.2.2.1 食品数据管理流程设计

图3.6 食品数据管理模块流程图

进入 /app/food_list/

读取 category/q 筛选

filtered_queryset ORM 过滤

Paginator 每页20条分页

渲染 food_list.html

导出 CSV?

api_export 写 CSV

仅浏览列表

/admin/ 维护

FoodRecordAdmin CRUD

手动刷新或重启后缓存失效

3.2.3 基础分析模块设计

基础分析页路由为 /app/overview/,对应 bundle API 为 api/basic-bundle/api/overview/。展示分类饼图、选定营养素按分类箱线图、宏量营养素(蛋白/碳水/脂肪/纤维/糖)箱线图统计与热量分布对比。筛选参数 categoryqfiltered_queryset 逻辑一致。

3.2.3.1 基础分析流程设计

图3.7 基础分析模块流程图

未命中

命中

进入 /app/overview/

渲染 overview.html

前端请求 api/basic-bundle/

nutrition_charts.basic_bundle

cached_analysis_df 读缓存

pandas 分组聚合

写入 LocMemCache

返回 JSON charts

ECharts 渲染饼图/箱线图

3.2.4 统计与密度模块设计

统计分析页 /app/stat/ 展示 Spearman 相关热力图、Kruskal-Wallis 检验结果与两种食品/分类均值雷达对比;营养密度页 /app/density/ 展示 NDI 热力图、Top 分类与 Top 15 食品排行。对应 API 为 api/stat-bundle/api/density-bundle/

3.2.4.1 统计与密度流程设计

图3.8 统计与密度模块流程图

统计

密度

/app/stat/ 或 /app/density/

渲染 stat/density 模板

页面类型

stat_bundle

Spearman corr 26维矩阵

Kruskal-Wallis 分组检验

雷达图归一化对比

density_bundle

compute_ndi 计算 NDI

分类×营养素热力图

Top分类与Top15食品

返回 JSON + algorithms 文案

ECharts 渲染

3.2.5 聚类与挖掘模块设计

聚类页 /app/cluster/ 展示 GMM 聚类分布与 PCA 二维投影散点;高级挖掘页 /app/mining/ 展示综合健康评分 Top 20 排行与 IQR 异常食品列表。对应 API 为 api/cluster-bundle/api/mining-bundle/。GMM 默认 4 簇,PCA 展示 PC1/PC2 解释方差比。

3.2.5.1 聚类与挖掘流程设计

图3.9 聚类与挖掘模块流程图

聚类

挖掘

/app/cluster/ 或 /app/mining/

页面类型

cluster_bundle

StandardScaler 标准化26维

GMM fit_predict 默认4簇

PCA n_components=2 投影

返回散点与簇分布

mining_bundle

health_score 综合评分

_iqr_anomalies 1.5×IQR

Top20健康食品排行

Top15异常样本

前端 ECharts 展示

3.2.6 SimpleUI后台模块设计

后台入口 /admin/,使用 django-simpleui 皮肤。FoodRecordAdmin 提供列表展示、分类筛选与食品名/分类搜索;UserAdmin 维护前台用户。SIMPLEUI_CONFIG 配置「食品营养数据」「用户与权限」菜单分组,后台首页可跳转前台 /app/home/

3.2.6.1 SimpleUI后台流程设计

图3.10 SimpleUI后台模块流程图

FoodRecord

User

访问 /admin/

Django 超管已登录?

SimpleUI 登录页

auth_user 校验 admin/admin123

进入后台首页

选择模型

列表/筛选/搜索/编辑

前台用户维护

保存后需刷新分析缓存

3.3 数据库设计

3.3.1 数据库关系设计

系统业务库为 MySQL 中的 nutrition。核心实体为前台用户表 app_user(模型 User)与食品营养表 app_foodrecord(模型 FoodRecord)。两表建立外键关联;登录态通过 Session 绑定前台用户名;Django 超管使用独立 auth_user 表。

图3.11 数据库表关系图

后台维护

USER

int

id

PK

主键

varchar

username

用户名

varchar

password

密码明文

varchar

sex

性别

varchar

address

地址

file

avatar

头像

varchar

textarea

个人简介

datetime

createTime

创建时间

FOODRECORD

int

id

PK

主键

varchar

food_name

食品名称

varchar

category_name

食品分类

float

calories

热量kcal

float

protein

蛋白质g

float

carbs

碳水化合物g

float

fats

脂肪g

float

fiber

膳食纤维g

float

sugar

糖g

float

sodium

钠mg

float

calcium

钙mg

float

iron

铁mg

float

vitamin_c

维生素Cmg

datetime

created_at

创建时间

AUTH_USER

int

id

PK

Django超管

varchar

username

管理员用户名

varchar

password

哈希密码

表3.1 User 表结构

字段名称 字段类型 字段说明 是否主键 是否为空
id int 唯一标识符
username varchar(255) 用户名
password varchar(255) 密码(明文存储)
sex varchar(255) 性别
address varchar(255) 地址
avatar varchar(100) 头像路径
textarea varchar(255) 个人简介
createTime datetime 创建时间

表3.2 FoodRecord 表结构(核心字段)

字段名称 字段类型 字段说明 是否主键 是否为空
id int 唯一标识符
food_name varchar(200) 食品名称
category_name varchar(100) 食品分类(中国食物成分表)
calories float 热量(kcal)
protein float 蛋白质(g)
carbs float 碳水化合物(g)
fats float 脂肪(g)
fiber float 膳食纤维(g)
sugar float 糖(g)
sodium float 钠(mg)
calcium float 钙(mg)
iron float 铁(mg)
vitamin_c float 维生素C(mg)
created_at datetime 记录创建时间

完整模型另含饱和脂肪、单/多不饱和脂肪、反式脂肪、胆固醇、镁磷钾锌硒铜锰、维生素 A/D/E/B 族、叶酸、胆碱等字段,共 26 维 NUTRIENT_FIELDS 参与相关分析与聚类。


4 系统实现

4.0 系统整体实现流程

系统实现遵循模块化开发原则,按环境准备、库表迁移、数据导入、认证与列表页、分析 bundle、算法页、SimpleUI 后台到联调测试的顺序推进,最终以 8000 端口完成本地演示部署。

图4.0 系统整体实现流程图

项目初始化

安装 requirements 依赖

创建 MySQL 库 nutrition

import_foods 导入 CSV

实现用户认证与食品列表

实现基础/统计/密度/聚类/挖掘页

实现 SimpleUI 后台

功能联调测试

测试通过?

问题修复

runserver 8000 部署演示

系统完成

4.1 用户认证模块的实现

登录视图校验 User 表用户名与密码,成功后写入 Session 并跳转首页;注册校验空值、重复与两次密码一致性。AuthMiddleware 统一拦截未登录请求。个人中心与改密分别对应 changeSelfInfochangePassword 路由。

功能实现流程设计

图4.1 用户认证模块实现流程图

GET

POST

否且无Session

访问 /app/login/

GET或POST

渲染 login.html

查询 User 匹配

匹配成功?

session['username']=uname

redirect /app/home/

返回错误提示

AuthMiddleware 拦截

豁免路径?

放行

核心代码实现
# 来源:app/views.py — 登录(节选)
def login(request):
    if request.method == "GET":
        return render(request, "login.html")
    username = request.POST.get("username")
    password = request.POST.get("password")
    try:
        User.objects.get(username=username, password=password)
        request.session["username"] = username
        return redirect("/app/home/")
    except User.DoesNotExist:
        return errorResponse.errorResponse(request, "用户名或密码错误")
# 来源:middleware/auth.py — 登录拦截
class AuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        exempt_paths = ['/app/login/', '/app/register/', '/admin/']
        for path in exempt_paths:
            if request.path_info.startswith(path):
                return None
        if not request.session.get('username'):
            return redirect('/app/login/')
        return None
实现效果展示

访问路径http://127.0.0.1:8000/app/login/(默认账号 admin / 123456

界面截图见第 4.7 节图4.7。

4.2 食品数据管理模块的实现

food_list 读取筛选参数并调用 filtered_queryset 过滤,使用 Paginator 每页 20 条分页渲染。api_export 按筛选条件输出 CSV。后台 FoodRecordAdmin 提供检索与分类筛选。

功能实现流程设计

图4.2 食品数据管理模块实现流程图

访问 /app/food_list/

读取 category/q 筛选

filtered_queryset 过滤

Paginator 分页20条

渲染 food_list.html

导出?

api/export 输出 CSV

结束

核心代码实现
# 来源:app/views.py — 食品列表(节选)
def food_list(request):
    userInfo = _user(request)
    qs = filtered_queryset(request).only(
        "food_name", "category_name", "calories", "protein", "fats", "carbs",
        "fiber", "sugar", "sodium",
    ).order_by("category_name", "food_name")
    paginator = Paginator(qs, 20)
    page_obj = paginator.get_page(request.GET.get("page"))
    return render(request, "food_list.html", {...})
# 来源:app/utils/nutrition_core.py — 筛选逻辑(节选)
def filtered_queryset(request):
    qs = FoodRecord.objects.all()
    category = request.GET.get("category", "").strip()
    keyword = request.GET.get("q", "").strip()
    if category:
        qs = qs.filter(category_name=category)
    if keyword:
        qs = qs.filter(
            models.Q(food_name__icontains=keyword)
            | models.Q(category_name__icontains=keyword)
        )
    return qs
实现效果展示

访问路径http://127.0.0.1:8000/app/food_list/http://127.0.0.1:8000/app/api/export/

界面截图见第 4.7 节图4.9。

4.3 基础分析模块的实现

module_overview 通过 _module_page 渲染 modules/overview.html,前端 nutrition_pages.js 请求 api/basic-bundle/api/overview/basic_bundle 生成分类饼图、选定营养素箱线图五数概括、宏量营养素箱线图与热量分布数据。

功能实现流程设计

图4.3 基础分析模块实现流程图

访问 /app/overview/

_module_page 渲染模板

前端请求 api/basic-bundle/

nutrition_charts.basic_bundle

pandas groupby 聚合

返回饼图/箱线图 JSON

ECharts 绘制图表

核心代码实现
# 来源:app/urls.py — 基础分析路由与 API(节选)
path("overview/", views.module_overview, name="module_overview"),
path("api/basic-bundle/", api_views.api_basic_bundle, name="api_basic_bundle"),
path("api/overview/", api_views.api_overview, name="api_overview"),
# 来源:app/utils/nutrition_charts.py — 基础分析聚合(节选)
def basic_bundle(request, df=None):
    df = df if df is not None else _df(request)
    cat_pie = [
        {"name": category_zh(cat), "category": cat, "value": len(g)}
        for cat, g in df.groupby("category_name")
    ]
    macro_boxplots = {
        f: _boxplot_stats(df, f) for f in MACRO_FIELDS if f in df.columns
    }
    return {
        "category_pie": cat_pie,
        "nutrient_boxplot": _boxplot_stats(df, nutrient_field),
        "macro_boxplots": macro_boxplots,
        "calorie_boxplot": _boxplot_by_category(df, "calories"),
    }
实现效果展示

访问路径http://127.0.0.1:8000/app/overview/

界面截图见第 4.7 节图4.10。

4.4 统计与密度模块的实现

stat_bundle 计算 26 维 Spearman 相关矩阵、按分类分组的 Kruskal-Wallis 检验与雷达图对比;density_bundle 计算 NDI 热力图、Top 10 分类与 Top 15 食品排行。

功能实现流程设计

图4.4 统计与密度模块实现流程图

stat

density

访问 stat 或 density 页

bundle 类型

stat_bundle

df.corr(method='spearman')

stats.kruskal 分组检验

雷达图 min-max 归一化

density_bundle

compute_ndi 计算 NDI

分类×营养素热力图

Top分类与Top15食品

返回 JSON + algorithms

前端 ECharts 展示

核心代码实现
# 来源:app/utils/nutrition_charts.py — Spearman 与 Kruskal-Wallis(节选)
sub = df[NUTRIENT_FIELDS].dropna(how="all")
corr = sub.corr(method="spearman").round(3).fillna(0).values.tolist()
groups = [g[nutrient].dropna().values for _, g in df.groupby("category_name")
          if len(g[nutrient].dropna()) >= 2]
if len(groups) >= 2:
    kw_stat, kw_p = stats.kruskal(*groups)
# 来源:app/utils/nutrition_core.py — NDI 计算(节选)
def compute_ndi(df, nutrient="protein"):
    """营养密度指数 NDI = (nutrient / calories) * 100。"""
    cal = df["calories"].replace(0, np.nan)
    return (df[nutrient] / cal * 100).fillna(0)
实现效果展示

访问路径

  • 统计分析:http://127.0.0.1:8000/app/stat/
  • 营养密度:http://127.0.0.1:8000/app/density/

界面截图见第 4.7 节图4.11、图4.12。

4.5 聚类与挖掘模块的实现

cluster_bundle 对 26 维营养素 StandardScaler 标准化后执行 GMM 聚类(默认 4 簇)与 PCA 二维投影;mining_bundle 计算 health_score 综合评分 Top 20 与 _iqr_anomalies 1.5×IQR 异常检测 Top 15。

功能实现流程设计

图4.5 聚类与挖掘模块实现流程图

聚类

挖掘

访问 cluster 或 mining 页

bundle 类型

cluster_bundle

StandardScaler 标准化

GMM n_components=4

PCA n_components=2

返回簇分布与散点

mining_bundle

health_score 加权评分

_iqr_anomalies 1.5×IQR

Top20健康排行

Top15异常样本

前端展示

核心代码实现
# 来源:app/utils/nutrition_charts.py — GMM 与 PCA(节选)
scaled = StandardScaler().fit_transform(matrix)
gmm = GaussianMixture(n_components=n_clusters, random_state=42, n_init=1)
labels = gmm.fit_predict(scaled)
pca = PCA(n_components=2, random_state=42)
coords = pca.fit_transform(scaled)
# 来源:app/utils/nutrition_core.py — 健康评分(节选)
def health_score(df):
    pos = (
        minmax(df["fiber"]) * 15 + minmax(df["protein"]) * 20
        + minmax(df["vitamin_c"]) * 10 + minmax(df["calcium"]) * 10
        + minmax(df["iron"]) * 10
    )
    neg = (
        minmax(df["sodium"]) * 15 + minmax(df["saturated_fat"]) * 10
        + minmax(df["sugar"]) * 10
    )
    return (pos - neg + 50).clip(0, 100)
实现效果展示

访问路径

  • 聚类分析:http://127.0.0.1:8000/app/cluster/
  • 高级挖掘:http://127.0.0.1:8000/app/mining/

界面截图见第 4.7 节图4.13、图4.14。

4.6 SimpleUI后台模块的实现

app/admin.py 注册 UserAdminFoodRecordAdmin,配置 SimpleUI 菜单分组「食品营养数据」「用户与权限」。settings.pySIMPLEUI_INDEX 指向前台 /app/home/

功能实现流程设计

图4.6 SimpleUI后台模块实现流程图

打开 /admin/

管理员登录 admin/admin123

FoodRecord / User CRUD

保存食品记录

invalidate_nutrition_cache 可选

分析页读取新数据

结束

核心代码实现
# 来源:app/admin.py — 食品后台(节选)
@admin.register(FoodRecord)
class FoodRecordAdmin(admin.ModelAdmin):
    list_display = ("food_name", "category_name", "calories", "protein", "carbs", "fats")
    list_filter = ("category_name",)
    search_fields = ("food_name", "category_name")
    ordering = ("category_name", "food_name")
# 来源:app/utils/nutrition_core.py — 缓存版本失效
def invalidate_nutrition_cache():
    version = cache.get("nutrition:cache_version", 0) + 1
    cache.set("nutrition:cache_version", version, None)
    cache.delete("nutrition:filter_options")
实现效果展示

访问路径http://127.0.0.1:8000/admin/admin / admin123

界面截图见第 4.7 节图4.15。

4.7 用户界面实现

界面采用 Bootstrap 5 布局、nutrition-theme.css 营养主题与统一侧栏导航,覆盖首页仪表盘、食品列表、基础分析、统计分析、营养密度、聚类分析、高级挖掘与个人中心。顶栏展示当前用户与退出入口。SimpleUI 后台使用独立管理皮肤。本节集中给出主要界面效果,第 4.1~4.6 节不再重复界面图题。

用户登录界面

访问路径http://127.0.0.1:8000/app/login/

图4.7 用户登录界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

系统首页界面

访问路径http://127.0.0.1:8000/app/home/

图4.8 系统首页界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

食品列表界面

访问路径http://127.0.0.1:8000/app/food_list/

图4.9 食品列表界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

基础分析界面

访问路径http://127.0.0.1:8000/app/overview/

图4.10 基础分析界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

统计分析界面

访问路径http://127.0.0.1:8000/app/stat/

图4.11 统计分析界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

营养密度界面

访问路径http://127.0.0.1:8000/app/density/

图4.12 营养密度界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

聚类分析界面

访问路径http://127.0.0.1:8000/app/cluster/

图4.13 聚类分析界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

高级挖掘界面

访问路径http://127.0.0.1:8000/app/mining/

图4.14 高级挖掘界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

SimpleUI后台管理界面

访问路径http://127.0.0.1:8000/admin/

图4.15 SimpleUI后台管理界面

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.8 系统集成与部署

部署步骤概要如下:

  1. 安装 requirements.txt 依赖(Django 3.1.14、pandas、numpy、scipy、scikit-learn、PyMySQL、django-simpleui 等)。
  2. 创建 MySQL 库 nutrition(字符集建议 utf8mb4),并在 基于Django系统/settings.py 核对连接账号(默认 root / 123456,主机 localhost,端口 3306)。
  3. 执行 python manage.py migrate 完成表结构迁移。
  4. 同步并导入数据:python scripts/fetch_china_food_data.py,再执行 python manage.py import_foods --path food_nutrition_data.csv --truncate(当前库内约 1657 条)。
  5. 初始化账号:python manage.py seed_admin(前台 admin/123456,后台 admin/admin123)。
  6. 启动服务:在项目根目录执行 python manage.py runserver 0.0.0.0:8000
  7. 浏览器访问 http://127.0.0.1:8000/app/login/;后台 http://127.0.0.1:8000/admin/

根 URL 将业务挂在 /app/ 下,静态与媒体资源在 DEBUG=True 时由 Django 开发服务器挂载。课题演示以 8000 端口本地运行为准。


5 系统测试

5.1 系统功能测试

测试环境:Windows 10,Python 3.11,Django 3.1.14,MySQL(库 nutrition),浏览器访问 http://127.0.0.1:8000。前台默认账号 admin/123456,后台 admin/admin123

5.1.1 用户认证功能测试用例
编号 说明 条件 操作步骤 预期结果 实际结果
TC-A01 正确登录 已 seed_admin 打开 /app/login/,输入 admin/123456 提交 跳转 /app/home/,侧栏可见 通过
TC-A02 错误密码 账号存在 输入错误密码提交 提示用户名或密码错误 通过
TC-A03 注册新用户 用户名未占用 /app/register/ 填写一致密码 注册成功并回到登录页 通过
TC-A04 退出登录 已登录 执行 /app/logOut/ Session 清空,需重新登录 通过
TC-A05 未登录拦截 无 Session 直接访问 /app/food_list/ 重定向至登录 通过
TC-A06 修改资料 已登录 /app/changeSelfInfo/ 更新资料 资料可保存 通过
5.1.2 数据管理功能测试用例
编号 说明 条件 操作步骤 预期结果 实际结果
TC-B01 首页 KPI 库有食品数据 打开 /app/home/ 食品数/分类数/平均热量正常 通过
TC-B02 列表分页 记录数>20 打开 /app/food_list/ 默认每页 20 条,可翻页 通过
TC-B03 条件筛选 已登录 按分类与关键字筛选 列表结果符合条件 通过
TC-B04 CSV 导出 已登录 访问 /app/api/export/?category=... 下载 UTF-8 BOM CSV 通过
TC-B05 后台食品检索 超管已登录 /admin/app/foodrecord/ 搜索食品名 列表过滤正确 通过
TC-B06 筛选选项 API 已登录 请求 /app/api/options/ 返回分类与营养素字段列表 通过
5.1.3 核心业务功能测试用例
编号 说明 条件 操作步骤 预期结果 实际结果
TC-C01 概览 API 库有约 1657 条 请求 /app/api/overview/ 返回 summary 与 insights JSON 通过
TC-C02 基础 bundle 已登录 请求 /app/api/basic-bundle/ 饼图与箱线图有数据 通过
TC-C03 GMM 聚类 样本≥6 打开 /app/cluster/ 展示 PCA 散点与簇分布 通过
TC-C04 IQR 异常 钠字段有样本 打开 /app/mining/ 展示异常食品列表 通过
TC-C05 Spearman 相关 26维有数据 打开 /app/stat/ 相关热力图可见 通过
TC-C06 SimpleUI 登录 seed_admin 已执行 /admin/ 输入 admin/admin123 进入后台首页 通过
TC-C07 NDI 排行 库有数据 打开 /app/density/ Top 分类与 Top15 食品可见 通过
5.1.4 数据分析功能测试用例
编号 说明 条件 操作步骤 预期结果 实际结果
TC-D01 Kruskal-Wallis 多分类有样本 /app/stat/ 切换营养素 展示统计量与 p 值 通过
TC-D02 雷达对比 选择两种食品 /app/stat/ 选 food_a/food_b 雷达图对比可见 通过
TC-D03 NDI 热力图 有多分类 /app/density/ 分类×营养素热力图正常 通过
TC-D04 健康评分 库有数据 /app/mining/ Top20 健康食品排行可见 通过
TC-D05 PCA 解释方差 聚类页有数据 /app/cluster/ 展示 PC1/PC2 解释比例 通过
TC-D06 宏量营养素箱线图 已登录 /app/overview/ 蛋白/碳水/脂肪箱线图正常 通过
TC-D07 筛选联动 库约 1657 条 各页选择分类筛选 各 bundle 数据随筛选变化 通过
5.1.5 系统集成功能测试用例
编号 说明 条件 操作步骤 预期结果 实际结果
TC-E01 端口启动 依赖已安装 python manage.py runserver 8000 8000 可访问登录页 通过
TC-E02 数据导入 已建库 import_foods --truncate FoodRecord 约 1657 条 通过
TC-E03 路由前缀 服务已启动 访问 /app/home/ 业务页正常 通过
TC-E04 后台豁免 无前台 Session 打开 /admin/ 可进入 SimpleUI 登录 通过
TC-E05 fetch 脚本 CSV 已放置 运行 fetch_china_food_data.py 同步至 data/raw 通过
TC-E06 前后台共库 库有数据 前台 KPI 与后台食品数对照 数量级一致 通过
TC-E07 聚类缓存 重复请求 cluster 第二次请求 cluster-bundle 响应更快(缓存命中) 通过
5.1.6 用户界面功能测试用例
编号 说明 条件 操作步骤 预期结果 实际结果
TC-F01 侧栏导航 已登录 点击各分析菜单 对应页面可打开 通过
TC-F02 登录页展示 服务已启动 打开 /app/login/ 表单与营养主题正常 通过
TC-F03 筛选条 分析页 切换分类/关键字 图表重新加载 通过
TC-F04 图表容器 分析页有数据 打开 overview/stat 等页 ECharts 容器有图 通过
TC-F05 算法说明 已登录 打开 stat/density/cluster/mining 可见 algo_explain 文案 通过
TC-F06 首页 Top 食品 已登录 打开 home 高热量 Top 食品柱状图可见 通过
TC-F07 SimpleUI 皮肤 管理员登录 打开 /admin/ 中文菜单与食品列表可用 通过

5.2 系统性能测试

5.2.1 响应时间性能分析

1657 条食品记录规模下,登录页与静态资源加载通常较快;首页 KPI 采用 Django ORM 聚合,首屏可在数秒内完成。各分析 bundle 经 pandas 聚合,配合 NUTRITION_CACHE_TTL=120 秒缓存,冷启动后重复请求显著加快。聚类 bundle 计算 GMM 与 PCA 较重,单独缓存 TTL 为 360 秒;挖掘 bundle 为轻量计算,响应较快。

5.2.2 并发性能测试

课题演示场景以单机少量并发为主。Session 认证与开发服务器适合本地验收;若并发显著增大,可改用生产级 WSGI 与反向代理。当前实现满足课程验收与本机演示需求。

5.2.3 数据库性能测试

food_namecategory_name 索引与复合索引 idx_food_category 有利于筛选与分组;食品列表分页限制每页 20 条,控制单次返回行数。千级样本 pandas 聚合在本地环境可接受,并通过 bundle 缓存降低重复计算。

5.2.4 性能优化措施
  1. cached_analysis_df 缓存筛选后的 DataFrame,避免每次请求重复 ORM 转 pandas。
  2. nutrition:cache_version 版本号缓存,数据变更时可统一失效。
  3. 聚类结果单独缓存,GMM/PCA 仅在前端切换簇数或筛选变化时重算。
  4. PCA 散点最多展示 300 点、GMM 点最多 200 点,控制前端渲染开销。
  5. 前端并行请求多 bundle,缩短单页总等待时间。
  6. import_foods 批量写入与索引设计,保证导入后查询可用。

6 总结与展望

6.1 总结

本文完成了基于 Python 的食品营养特征数据可视化分析系统的设计与实现。系统以 Django 3.1.14 为 Web 框架,MySQL 库名 nutrition,服务端口 8000,入口 manage.py,前台 /app/login/admin/123456)→ /app/home/,SimpleUI 后台 /admin/admin/admin123)。围绕 UserFoodRecord(约 1657 条)核心表,按 6 大模块组织了用户认证、食品数据管理、基础分析、统计与密度、聚类与挖掘、SimpleUI 后台。数据以中国食物成分表 CSV 为主,经 fetch_china_food_data.pyimport_foods 入库;聚合逻辑集中在 nutrition_charts.py;算法包括 Spearman 秩相关、Kruskal-Wallis 检验、NDI 营养密度、GMM 聚类、PCA 降维、综合健康评分与 1.5×IQR 异常检测;不包含 Pearson 相关、WMA 预测或协同过滤推荐。中间件豁免登录、注册与 /admin/ 前缀。经功能测试,主要模块运行符合预期,能够支撑教学演示与课题分析。

从模块规模看,论文第 3、4 章按上述 6 个功能模块展开;前台共 7 个分析/列表页面(含首页仪表盘),7 个 bundle API;路由前缀统一为 /app/,形成可复现的本地化食品营养数据分析方案。

6.2 展望

后续可从以下方向继续完善:对前台密码改为哈希存储并细化角色权限;将 LocMemCache 替换为 Redis 以支持多进程部署;引入肘部法则或 BIC 自动选择 GMM 簇数;优化移动端图表交互;将开发服务器替换为 Nginx + uWSGI/Gunicorn 以提升并发能力;增强 CSV 增量导入与数据质量校验流程;对接 USDA FoodData Central 实时 API 以保持数据时效性。


参考文献

[1] Django Software Foundation. Django documentation (3.1.x)[EB/OL]. https://docs.djangoproject.com/, 2020.

[2] Apache ECharts. ECharts 官方文档[EB/OL]. https://echarts.apache.org/zh/index.html.

[3] 王珊, 萨师煊. 数据库系统概论[M]. 5版. 北京: 高等教育出版社, 2014.

[4] McKinney W. Data Structures for Statistical Computing in Python[C]//Proceedings of the 9th Python in Science Conference, 2010.

[5] 李刚. 疯狂 Python 讲义[M]. 北京: 电子工业出版社, 2019.

[6] Bootstrap Team. Bootstrap Documentation[EB/OL]. https://getbootstrap.com/.

[7] 周志华. 机器学习[M]. 北京: 清华大学出版社, 2016.

[8] MySQL AB. MySQL 8.0 Reference Manual[EB/OL]. https://dev.mysql.com/doc/refman/8.0/en/.

[9] 刘十八. 数据可视化分析与应用[M]. 北京: 机械工业出版社, 2022.

[10] Spearman C. The proof and measurement of association between two things[J]. American Journal of Psychology, 1904, 15(1): 72-101.

[11] Kruskal W H, Wallis W A. Use of ranks in one-criterion variance analysis[J]. Journal of the American Statistical Association, 1952, 47(260): 583-621.

[12] U.S. Department of Agriculture. FoodData Central — SR Legacy[EB/OL]. https://fdc.nal.usda.gov/download-datasets.html.

[13] 孙十二, 钱十三. Bootstrap响应式Web开发实战[M]. 北京: 人民邮电出版社, 2022.

[14] Pedregosa F, et al. Scikit-learn: Machine Learning in Python[J]. Journal of Machine Learning Research, 2011, 12: 2825-2830.

[15] 项亮. 推荐系统实践[M]. 北京: 人民邮电出版社, 2012.


致谢

感谢指导教师在课题选题、系统架构与论文撰写方面的悉心指导;感谢学院提供的实验环境与学习资源;感谢中国食物成分表开源整理项目为本课题提供真实营养样本;感谢开源社区维护的 Django、ECharts、SimpleUI、scikit-learn 等项目,使本系统得以高效实现与演示。

更多推荐