No description
- Python 62.6%
- Cython 17%
- C 13.3%
- HTML 3.4%
- XSLT 2.8%
- Other 0.9%
| .idea | ||
| .pydeps | ||
| __pycache__ | ||
| b95dc-main | ||
| data | ||
| price | ||
| pydeps | ||
| static | ||
| templates | ||
| app.py | ||
| db.py | ||
| db_config.py | ||
| desktop.ini | ||
| import_douguo.py | ||
| ingredient_mapping.py | ||
| normalize_cuisines.py | ||
| README.md | ||
| requirements.txt | ||
食材宇宙(Food Universe)
一个基于 Flask + MySQL 的食材/菜谱数据分析与可视化网站,涵盖菜谱管理、冰箱选材推荐、菜场行情、食材关系分析四大功能,并内置用户账号体系(收藏、个性化推荐、游客冰箱跨设备同步)与用户上传菜谱 + 管理员人工审核机制。
功能模块
| 页面 | 路由 | 说明 |
|---|---|---|
| 首页 | / |
数据概览仪表盘(食材词云 + 统计图表) |
| 冰箱选材 | /fridge |
把冰箱里的食材加入列表,智能推荐可做的菜 |
| 食材关系 | /universe |
D3 力导向图展示食材搭配关系(支持度/提升度) |
| 菜场行情 | /market |
食材价格走势、对比与性价比推荐 |
| 随机推荐 | /scratch |
刮刮乐式随机推荐菜谱 |
| 菜谱查询 | /browse |
只读菜谱搜索/查看(普通用户/游客)+ 用户上传菜谱 |
| 后台管理 | /admin |
菜谱的增删改查 + 用户上传菜谱的人工审核 |
技术栈
- 后端:Python 3 + Flask + PyMySQL + pandas
- 数据库:MySQL(库名
food_universe) - 前端:原生 HTML/CSS/JS + D3.js + ECharts(公共脚本/样式/模板片段已抽离为共享模块,详见下方「前端模块化」)
目录结构
foodnew/
├─ app.py # 入口 + 全部路由(控制器层,含登录校验与操作日志)
├─ db.py # 数据库读写(数据访问层,含关系图缓存 + 操作日志表)
├─ db_config.py # MySQL 连接配置 + 后台管理员登录配置
├─ ingredient_mapping.py # 食材名标准化 + 分类映射
├─ import_douguo.py # 从豆果数据导入菜谱
├─ requirements.txt # Python 依赖清单
├─ templates/ # 页面模板(视图层)
│ ├─ index/fridge/universe/market/admin/scratch/browse.html # 各功能页面
│ └─ _navbar.html / _footer.html / _background.html # 共享模板片段
├─ static/
│ ├─ css/common.css # 共享样式(背景块 + 全局重置)
│ ├─ js/utils.js # 共享前端工具(htmlEscape / fetchJSON)
│ └─ ... # 第三方库 / 背景图
├─ data/ # 关联规则分析脚本
└─ price/ # 价格 CSV 原始数据 + 导入脚本
前端模块化
公共资源已从各页面抽离为共享模块,改一处即全站生效:
templates/_navbar.html:共享导航栏,按request.path自动高亮当前页,并条件渲染「冰箱数量徽标」「用户登录区」以及按身份区分的「管理 / 菜谱查询」入口。templates/_footer.html:共享页脚,文案可用footer_text覆盖。templates/_background.html:共享蔬菜背景 + 水印大字。static/css/common.css:多个页面共用的全局样式(背景块 + 重置)。static/js/utils.js:跨页面共用的 JS 工具函数(FoodUtils.htmlEscape/FoodUtils.fetchJSON)。
各页面的
body、.navbar、.container、.btn、.card等因存在页面级差异,仍保留在各页面内联样式中。
快速开始
1. 安装依赖
pip install -r requirements.txt
依赖项:flask、pandas、pymysql。
2. 配置数据库
编辑 db_config.py,填入你自己的 MySQL 连接信息:
DB_CONFIG = {
'host': 'localhost',
'port': 3306,
'user': 'root',
'password': '你的密码',
'database': 'food_universe',
'charset': 'utf8mb4'
}
确保 MySQL 中已创建 food_universe 数据库:
CREATE DATABASE IF NOT EXISTS food_universe DEFAULT CHARSET utf8mb4;
3. 初始化数据
项目涉及多张表,会在代码运行时按需自动建表:
| 表名 | 说明 | 建表位置 |
|---|---|---|
recipes |
菜谱主表 | import_douguo.py |
recipe_ingredients |
菜谱-食材关联表 | db.py |
ingredient_prices |
食材价格表 | db.py |
fridge |
冰箱食材表 | db.py |
operation_logs |
后台管理操作日志 | db.py |
users |
用户端账号(含管理员标记) | db.py |
favorites |
用户收藏的菜谱 | db.py |
pending_recipes |
用户上传、待管理员审核的菜谱 | db.py |
导入菜谱数据:
python import_douguo.py
导入价格数据(来自北京市发改委 CSV,位于 price/ 目录):
python price/import_price_data.py
4. 启动服务
python app.py
启动时会在后台预加载「食材关系」的共现统计数据(约数秒,仅一次),之后访问页面秒开。浏览器打开 http://localhost:5000 即可。
主要 API
菜谱
GET /api/recipes?page=&per_page=&keyword=— 分页查询菜谱GET /api/recipe/<id>— 单个菜谱详情GET /api/ingredients— 食材列表GET /api/random_recipe— 随机菜谱POST /api/recommend— 按冰箱食材推荐(body:{"ingredients": [...]})
食材关系
GET /api/frequent_pairs?min_support=&limit=— 频繁搭配食材对(返回 nodes + links,含支持度/置信度/提升度)
菜场行情
GET /api/price/<ingredient>?type=&days=— 单个食材价格趋势GET /api/prices?type=— 所有食材最新价格GET /api/best_buys?limit=&type=— 性价比推荐GET /api/price_comparison?ingredients=a,b,c&type=— 多食材价格对比GET /api/prices_by_date?date=&type=— 指定日期价格GET /api/available_dates?type=— 可用日期列表
冰箱
GET /api/fridge?session=— 获取冰箱食材POST /api/fridge/add— 添加食材POST /api/fridge/remove— 移除食材POST /api/fridge/clear— 清空冰箱
用户账号 / 收藏
POST /api/auth/register— 注册(body:{"username","password","device_session"})POST /api/auth/login— 登录(登录后自动合并游客冰箱)POST /api/auth/logout— 退出GET /api/auth/status— 查询登录态(含is_admin)POST /api/auth/set_admin— 将某用户设为管理员(仅后台管理员)POST /api/favorites/toggle— 切换收藏(需登录)POST /api/favorites/remove— 取消收藏(需登录)GET /api/favorites/ids— 我收藏的菜谱 id 列表(需登录)GET /api/favorites/list— 我收藏的菜谱详情列表(需登录)POST /api/recommend/favorites— 收藏夹推荐:基于收藏菜谱食材匹配推荐(需登录)
游客的冰箱通过浏览器
device_session(设备 ID)隔离;登录后并入账号,实现跨设备同步与数据不丢失。 收藏同样基于账号:游客点收藏会先引导登录。
菜谱上传 / 审核
POST /api/recipe/upload— 登录用户上传菜谱(进入待审核队列)GET /api/admin/pending_recipes?status=— 后台获取待审核列表(pending/approved/rejected,需登录)POST /api/admin/pending_recipes/<id>/approve— 审核通过并发布(需登录)POST /api/admin/pending_recipes/<id>/reject— 审核驳回(需登录)GET /api/admin/pending_recipes/<id>/detail— 单条待审核菜谱详情(需登录)
后台管理
登录依赖 Flask Session,默认管理员账号由 db_config.py 配置(开发默认 admin / admin123)。新增/修改/删除菜谱、数据迁移、价格导入这些写接口均需先登录,未登录返回 401。
POST /api/admin/login— 管理员登录(body:{"username":"admin","password":"..."})POST /api/admin/logout— 退出登录GET /api/admin/status— 查询登录状态GET /api/admin/logs?limit=— 获取最近操作日志(需登录)POST /api/admin/recipe— 新增菜谱(需登录)PUT /api/admin/recipe/<id>— 更新菜谱(需登录)DELETE /api/admin/recipe/<id>— 删除菜谱(需登录)POST /api/migrate— 从 CSV 迁移菜谱(开发用,需登录)POST /api/import_price— 导入价格数据(需登录)
公开的只读接口(如
GET /api/recipes、GET /api/recipe/<id>)保持免登录,供首页/冰箱页使用。
设计说明
- 三层结构:
app.py(路由)→db.py(数据)→templates/(视图),职责分离,改 SQL 不动路由、加接口不动模板。 - 后台安全:危险写接口统一用
login_required装饰器做登录校验,并在operation_logs表中记录每次登录/增删改/导入操作(含用户名、IP、时间)。 - 两套登录体系:后台管理员(
db_config.py的ADMIN_USER,用is_admin标记)与用户端账号(users表,可注册、收集藏、is_admin标记为管理员的账号也可进入后台);导航栏「管理 / 菜谱查询」按身份条件渲染。 - 上传审核闭环:普通用户(
/browse)上传菜谱进入pending_recipes表待审核队列;管理员在后台逐条「通过(写入正式recipes)或驳回」,保证内容合法性,避免未经验证的菜谱直接上线。 - 食材关系性能:食材两两共现统计是重查询,已在最低支持度(0.5%)一次性预计算并缓存到内存,之后拖动支持度滑块仅做内存过滤,不再连库;服务启动时通过
warm_frequent_pairs()预加载,首次访问即秒开。 - 缓存失效:后台增/删/改菜谱后会调用
clear_frequent_pairs_cache()清空缓存,保证关系图数据实时更新。 - 前端模块化:公共脚本/样式/模板片段已抽离(见上方「目录结构 · 前端模块化」),各页面只保留自身特有的布局与图表逻辑。
备注
- 数据表
ingredient_prices已建(price_type, date)复合索引以加速菜场行情查询;价格排行前端做了分批渲染(每批 20 条)以提升大数据量下的流畅度。 .idea/、b95dc-main/分别为 IDE 配置与原始数据集,与运行代码无关。