1. 选型期的纠结:为什么最终定了 Django + 随机森林这套组合
1.1 毕业设计需求拆解:这套系统到底要解决哪些问题
每年的毕业设计季,我都能看到大量学生在"做点什么"上反复横跳。商品数据分析与销量预测这个题目,听起来很常规,但真正落地时你会发现它其实是一个综合性很强的工程——它同时考验了数据采集、存储设计、数据清洗、特征工程、算法理解、后端开发和前端可视化这七项能力。
先把这个题目的需求拆干净:目标对象是电商场景下的商品数据,核心任务有两块,第一块是对历史商品数据进行多维度的统计分析,比如价格分布、销量趋势、类目占比、评价情感倾向等;第二块是基于随机森林回归模型,对商品的未来销量做出预测。而这两块能力最终要通过 Django 框架整合成一个带 Web 界面的系统,让用户能通过浏览器查看分析图表、输入特征并获取预测结果。
这里有一个很多初学者容易踩的坑:拿到这个题目就开始写代码,结果做着做着发现数据没有、模型效果一塌糊涂、前端图表不知道怎么接。问题的根源在于没有把"系统"两个字当回事。毕业设计考核的是你搭建完整系统的能力,而不只是跑通一个模型。所以第一步应该是画清楚系统的模块边界和数据流向,把采集、存储、分析、建模、展示这五个环节单独拉出来审视。
1.2 技术选型的底层逻辑:不是所有热门技术都该往项目里塞
标题里挂着 Django、随机森林、爬虫、深度学习、大模型、大数据这些词,但我的建议非常直接:技术栈要服务毕业设计的可完成性和可答辩性,不要追热词。
先说框架。Django 在这个场景下的优势并不是"性能最强",而是"全家桶"式的完整性——ORM 让数据落库和查询变得非常顺手,Admin 后台可以直接用来管理商品数据和模型任务,自带的模板系统配合前端框架做可视化页面也很方便。如果用 Flask,你会发现自己要额外接 SQLAlchemy、额外的后台管理方案,工作量并不少。对于毕设来说,Django 的成熟生态能让你把更多精力放在模型和分析本身。
再说算法。为什么选随机森林而不是深度学习或者大模型?核心原因是样本量和可解释性。毕设场景下能拿到的商品历史数据通常是几千到几万条的水平,这个数据规模下,深度学习很难训出稳定优于随机森林的效果,反而会带来调参、训练时间、环境依赖的额外负担。而随机森林作为集成学习中的 Bagging 代表,对表格型数据的拟合能力强,训练速度快,还能直接输出特征重要性,这在写论文和答辩的时候都很好讲。大模型和深度学习可以作为系统的"扩展讨论"出现在论文里,但核心算法一定选稳的。
可视化方面,我强烈建议用 ECharts,而不是直接靠 Django 模板硬渲染。原因是 ECharts 的图表类型齐全、交互成熟,而且有 Python 配套的 pyecharts 库可以直接生成前端代码,省去你手写 JavaScript 的麻烦。说实话,能把 ECharts 和 Django 视图之间数据传递的机制讲清楚,在答辩中本身就是加分项。
2. 数据从哪来:爬虫采集链路的设计与反爬心理战
2.1 爬虫目标分析:先定数据源,再写代码
数据采集是整个项目的地基,没有真实数据,后面所有分析和模型的章节都会变得很虚。毕设场景下比较靠谱的商品数据源有几类:电商公开页面、商品评论接口、比价平台、行业数据公开集。我自己做的时候选的是电商平台的商品搜索页和详情页,因为这类页面数据结构化程度高,字段包含标题、价格、销量、评价数、上架时间等,正好满足分析需求。
这里要特别说明一点:千万不要一上来就写爬虫代码。先把目标页面在浏览器里打开,用开发者工具看 Network 面板,搞清楚哪些数据是后端接口返回的 JSON,哪些是服务端渲染的 HTML 片段。以我的经验,很多电商平台的列表数据都有对应的 JSON 接口,直接从接口拿数据,远比你用解析器从 HTML 里抠数据要稳定。接口返回的数据结构清晰、字段命名规范、翻页参数简单,唯一要处理的就是请求头和签名校验。
第一次做这个项目的人,我建议先用单个商品页做实验,跑通后再扩展到列表页,最后才是批量采集。一次性想把所有功能做完,往往会在第一轮就反被网站的验证码打败,非常打击信心。
2.2 反爬策略应对:从请求头伪装到请求频率控制
电商平台对爬虫的检测,说白了看三样东西:请求头是不是像正常人、请求频率是不是像人类、行为轨迹是不是有规律。针对这三样,我在项目里做了几层处理。
请求头伪装是最基础的,User-Agent 列表轮换、Referer 补全、Accept-Language 设置为中文环境,这些是基本操作。但要注意,很多网站现在会校验 TLS 指纹和 HTTP/2 指纹,单纯改 User-Agent 已经没有太大意义。如果你发现请求能发出但返回的是验证码页面或空数据,优先检查是不是指纹层面的问题,可以考虑用 curl_cffi 这种能模拟浏览器 TLS 指纹的库来替换 requests。
请求频率控制是很多人最容易忽略的部分。我见过太多人用 for 循环连续请求几百次,然后被封 IP。正确的做法是把请求间隔设为随机值,比如 2 到 5 秒之间随机波动,并且每个页面只请求一次,把数据落库后再继续下一个。这里我建议做一个简单的任务队列,用一个文本文件或者数据库表记录待采集的商品 ID 和采集状态,每完成一条就更新状态,这样即使某次采集中断了,重启后也能从断点继续,而不是全部重新跑一遍。
对于登录后才能看到的数据,我在毕设项目里建议你直接放弃,不要碰。原因很简单:登录态维护、验证码识别、账号风控,每一样都是无底洞,会把你拖进无限加班中。如果老师问起来,你可以说"系统实现的是公开数据的采集与分析,涉及用户登录态的数据涉及隐私合规问题,故不纳入本次设计",这个回答在合规层面也是更稳妥的。
2.3 数据存储设计:用 ORM 建模而不是随手扔进 CSV
数据采集之后,存储方式决定了后面分析模块的开发效率。很多人图省事,直接把数据存成 CSV 文件,用 pandas 一读了之。在毕设规模下这样确实可以跑通,但是一旦你要做 Web 系统,让用户通过浏览器查询不同条件下的分析结果,纯 CSV 的方式会让你陷入 IO 操作和内存管理的地狱。我的建议是用 Django ORM 建三张核心表:商品基础信息表、历史销量快照表、商品评价表。
商品基础信息表存的是商品的静态属性,比如商品 ID、标题、品牌、类目、价格、上架时间等。这里有个细节:价格字段不要用 FloatField,应该用 DecimalField 并指定 max_digits 和 decimal_places,否则在做金额相关的聚合统计时会出现浮点误差,很难解释清楚。
历史销量快照表是整个预测模型的关键。它记录的是每个商品在不同时间点的累计销量和可选的收藏数、评价数变化值。这张表的重要性在于,它让你可以从"累计值"推导出"增量",而增量才是时间序列预测真正需要的目标变量。很多人在做销量预测时直接用累计销量,结果模型性能一塌糊涂,其实就是在这里糊了。
评价表则用来做商品口碑维度的分析。如果你打算做文本情感分析,这一张表就是语料来源。
数据库选型直接用 SQLite 还是 MySQL?我的建议是,如果你的数据量在几万条以内,SQLite 完全够用,而且部署简单、答辩演示时不需要额外启动数据库服务。如果数据量很大或者你想展示"大数据处理"的能力,就换 MySQL,并配上 Redis 做缓存。不要为了"显得高级"而盲目上 HBase 或者大数据组件,那只会增加系统复杂度,还会在答辩现场给你挖坑。
3. 让数据在浏览器里说话:分析模块和可视化落地方案
3.1 指标体系设计:一张数据大屏到底放些啥
分析模块的核心不是有多少种图表,而是分析视角是否完整。我在这个项目里把分析维度分成四层:整体市场层、类目结构层、单品表现层、用户口碑层。
整体市场层看的是大盘数据,包括采集到的商品总数、总销量、平均价格、价格中位数、销量最高的店铺 TOP10、价格区间分布。这一层回答的是"市场上总体情况怎么样"。
类目结构层看的是不同类目之间的横向对比,包括各类目的商品数量占比、平均价格对比、销量贡献占比。这层回答的是"哪个类目最值得做"。
单品表现层聚焦于具体商品,包括单品的历史销量走势、价格调整记录、排名变化。这层回答的是"某一款商品卖得好不好、为什么好"。
用户口碑层则是对评论数据进行聚合,包括评分分布、评论数量随时间变化、高频关键词标签。这层回答的是"用户到底在意什么"。
建议你把这几层做成一个"数据总览大屏"页面,用卡片展示 KPI 数值,用柱状图展示价格分布和类目对比,用折线图展示销量趋势,用饼图展示评价星级分布。整体布局做成上中下三段式:顶部是核心指标卡片,中部是主图表区域,底部是明细表格。这个布局在答辩演示时非常占便宜,因为你一打开页面,评委就能在一屏之内看到整个系统的能力覆盖范围。
3.2 Django 视图层的数据聚合逻辑:不要在前端做计算
可视化模块最容易出现的问题是前端拿到原始数据后用 JavaScript 临时计算聚合值。这个习惯非常不好,你得把聚合逻辑放在 Django 视图层里,用 ORM 的 aggregate 和 annotate 方法来完成。
举个例子,要统计价格区间分布,我建议在视图里先通过 ORM 取出所有商品价格,然后用 pandas 的 cut 方法分箱,再统计每个区间的数量,最后把结果以 JSON 格式返回给前端。整个过程在服务端完成,前端只负责渲染。这样做的好处有两个:第一,测试方便,你可以直接在后端写单元测试验证聚合逻辑的正确性;第二,答辩时可以清晰地讲出"数据的消费流程"。
视图返回 JSON 的方式,我推荐用 JsonResponse,配合 Django 的原生序列化能力。如果你用了 Django REST Framework,那就用它的 Response 类,但要注意,不要为了省事序列化整个 ORM 对象集合,而是构造好字典列表后再返回。
前端图表渲染,我建议用 ECharts 的按需加载方式,不要一次性引入完整包。一个页面可能需要柱状图、折线图、饼图,完全可以把通用图表初始化逻辑抽成一个公共函数,每次请求到 JSON 数据后更新图表配置项。这里我踩过的坑是:第一次初始化图表时忘记设置 height,导致图表渲染在不可见的容器里高度为 0,刷新页面后才正常。遇到这种情况,检查 chart 容器是否在 DOM 加载完成之后才初始化,以及是否显式设置了容器高度。
3.3 筛选条件联动:让分析页面的价值翻倍
静态图表只能说明"有分析功能",动态联动才是分析模块的加分项。我在系统里加了一个顶部筛选栏,支持按时间范围、商品类目、价格区间三个维度联动筛选,每次切换筛选条件就重新向后端发起请求,后端基于新的条件重新聚合数据,返回更新后的 JSON。
这个设计的核心在于后端要支持动态条件拼接。用 Django ORM 写的话,可以构造一个 Q 对象列表,按条件逐个添加过滤条件,最后统一执行查询。注意别犯把所有数据加载到内存再用 Python 过滤的错,数据量小的时候无所谓,一旦数据量大就非常慢。我实测过,同样条件下,在 SQL 层过滤比在 Python 层过滤快一个数量级。
联动筛选中还有一个细节:时间范围筛选需要统一时间格式。前后端传参统一用 ISO 8601 字符串(比如 2025-01-01),后端用 datetime.strptime 解析,别用前端 toISOString 返回的时间戳格式直接拼接 SQL 条件,很容易因为时区问题导致查出来的数据缺失半天。
4. 随机森林销量预测模型:特征工程才是真正的胜负手
4.1 预测任务的定义:一句话说清楚要预测什么
建模之前必须把任务定义清楚。我在系统里做的销量预测任务是:给定某个商品在过去 N 天的销量序列和商品静态属性,预测未来 7 天的总销量。这里要澄清一下,这不是递归式的多步预测,而是直接以"未来 7 天合计销量"作为回归目标。这样做的原因是:随机森林是回归模型,不擅长做序列迭代预测;而把目标定义成一段时间内的合计值,单模型的训练和评估都更稳定。
有了明确的预测目标,就可以开始构造训练数据集了。每个样本的输入特征包含两部分:商品静态特征(类目、品牌、价格、上架时长)和历史销量统计特征(近 7 天销量、近 14 天销量、近 30 天销量、销量环比变化率、价格变动次数等)。
这里有个我最初犯过的错误:直接把所有商品的原始销量序列拉平作为训练集,导致模型学到了"商品 ID 记忆"而不是"销量规律"。这个问题在交叉验证时暴露得非常明显——训练集上 R² 高达 0.95,测试集上只有 0.3。解决办法是分批分组:在划分训练集和测试集时,必须保证同一天的样本不会同时出现在两边,更不能让同一个商品的时间序列被切断后分到两边。正确做法是按时间划分,比如用前 70% 的时间段做训练,后 30% 的时间段做测试。
4.2 特征工程实操:从原始字段到有效特征
特征工程这一步决定模型效果的上限。我整理了一份特征清单,按类别分为三类:
- 商品静态特征:价格、类目编码、品牌编码、上架天数、商品标题长度、图片数量。
- 销量统计特征:近 7/14/30 天销量之和、近 7 天销量均值、销量标准差、环比变化率、最大单日销量、最近一次销量为 0 的天数。
- 时间特征:记录日期是星期几、是否节假日、月份、季度。
类目和品牌这类文本型字段,不能直接塞给随机森林,需要做标签编码或者独热编码。我的建议是:如果类目数量少于 20 个,用独热编码;如果大于 20 个,用标签编码。原因是独热编码会在特征空间膨胀,而随机森林在做特征选择时对高基数类别特征的处理并不是特别优雅。
价格这个特征也需要处理,不要直接用原始值。价格区间差异巨大,比如 9.9 包邮和 4999 的数码产品,放到同一个模型里会让树的分裂变得不稳定。建议做对数变换,np.log1p(price),让价格分布更接近正态,模型的鲁棒性会好很多。
对于销量统计特征,有一个特别重要的细节:构造近 7 天销量时,要确保窗口是连续 7 个自然日,而不是最近 7 条记录。因为商品并不是每天都产生销量记录,如果某个商品 3 天没有更新销量快照,按记录数取窗口就会导致时间跨度过长,特征失真。这个问题我在做数据预处理时用 resample 方法按日重采样,缺失日期记 0,再滚动求和。
4.3 训练与调参:随机森林的参数其实没有那么多玄学
随机森林的核心参数就那么几个:n_estimators(树的数量)、max_depth(树的深度)、min_samples_split(内部节点再划分所需最小样本数)、min_samples_leaf(叶子节点最少样本数)、max_features(每次分裂时考虑的特征数)。
我实验下来的经验是,n_estimators 设到 200 到 500 就够用了,再往上增加树的数量边际收益很小,反而增加训练时间和模型体积。max_depth 控制在 10 到 20 之间,太深的树容易过拟合训练集,太浅又欠拟合。min_samples_leaf 建议设置成训练样本数的 1% 左右,这样可以防止树学到过于特化的模式。
如果你要系统性调参,可以用 GridSearchCV 做交叉验证搜索,但一定要控制搜索空间的大小,否则网格搜索会跑很久。我建议分两轮:第一轮用较大的步长粗搜 n_estimators 和 max_depth,找到大致范围;第二轮固定这两个值,细搜 min_samples_split 和 min_samples_leaf。
另外,训练模型时一定要设置 random_state 固定随机种子。这不仅是可复现性的要求,还能让你在调参时确认效果差异到底是参数带来的还是随机性带来的。我在项目中统一用 random_state=42。
模型评估指标我建议同时报告 R²、平均绝对误差(MAE)和均方根误差(RMSE)。R² 衡量的是模型解释了多少方差,MAE 比较直观——销量预测平均偏差了多少件,RMSE 对大幅偏差更敏感。答辩时如果你能把这三个指标放在一起解释,并说明它们分别对业务意味着什么,非常加分。
在测试集上我的随机森林模型 R² 在 0.85 左右,MAE 大概 20 件左右(对于日销几十到几百件的商品来说,这个精度是能接受的)。如果你发现你自己的模型效果明显偏差,优先检查数据泄露——看看训练集中是否混入了目标计算窗口内的信息。数据泄露是随机森林模型出现"虚假高精度"的最常见原因。
5. 模型怎么跑进 Web 系统:部署集成与技术债务处理
5.1 模型持久化:joblib 还是 pickle
训练好的随机森林模型需要保存到磁盘,然后在 Django 视图里加载并调用预测。我推荐用 joblib.dump 和 joblib.load,而不是 pickle。原因是 joblib 对包含大量 NumPy 数组的对象做了专门优化,序列化和反序列化速度更快,文件体积也更小。
保存模型时,最好把训练时用到的特征名列表也一并保存下来,就像这样:将特征名存成 features.json,模型存成 model.joblib。这样在 Django 视图里加载模型后,可以先校验传入的请求参数是否与特征列表匹配,避免因为前端传参遗漏导致预测时特征对齐错误。
我见过一个很隐蔽的坑:在训练脚本里用 pandas 处理特征,特征的顺序来自 DataFrame 的列顺序,一旦后来在 Django 里用字典构造特征,key 的顺序变了,特征顺序就完全错乱,模型的预测结果直接变成了废数据。解决办法是训练时显式地固定特征顺序列表,并在预测时按同一顺序构造数组。简要逻辑如下:
# 训练时保存特征顺序 feature_cols = ["category_code", "price_log", "sales_7d", "sales_30d", "price_change_count"] joblib.dump(model, "model.joblib") with open("features.json", "w", encoding="utf-8") as f: json.dump(feature_cols, f, ensure_ascii=False) # Django 视图加载时 model = joblib.load("model.joblib") with open("features.json", "r", encoding="utf-8") as f: feature_cols = json.load(f)5.2 预测接口设计:前端拿什么参数,后端返回什么结果
预测接口的设计思路是:前端传入商品的基础信息和近期销量数据,后端返回预测销量及置信区间。我在 Django REST Framework 里实现了一个 PredictView,接受 POST 请求,参数包括商品类目、价格、近 7/14/30 天销量等。
接口内部的处理流程是:先校验参数完整性,然后对价格做对数变换,接着构造特征数组,加载模型做预测,最后把预测值和特征重要性排名一起返回。这里我做了一个很实用的功能——特征归因分析。随机森林有个 feature_importances_ 属性,保存模型的时候一并把特征重要性存下来,预测时直接把当前请求的特征值按重要性排序返回给前端。前端展示"该商品预测销量为 238 件,其中销量惯性贡献最大,占 62%",这种呈现方式,答辩评委基本都会感兴趣。
预测结果还要考虑合理的展示范围。随机森林回归只能给出点预测,不能直接给出概率区间,但你可以用训练集的残差分布来近似构造置信区间——例如计算出训练集残差的标准差,预测值加减 1.65 倍标准差作为 90% 的置信区间。这个方法不完全严谨,但足够用于系统的业务解释,而且算法上的依据是残差不随输入变化的同方差假设,在销量规模变化不大的场景下是适用的。
5.3 Web 系统中模型管理的进阶思路:定时重训练
如果你希望系统看起来更完整,我建议加一个模型管理模块,支持手动上传训练数据、触发模型重训练、查看训练历史。这个模块的难度不大,无非是把训练脚本封装成 Django 管理命令,再用一个简单的任务状态表记录训练进程。
训练任务是阻塞式的还是异步的?在毕设场景下,数据量不大,训练只需几十秒,你可以用 Django 的同步接口跑,但是要在接口里做超时保护。为了展示你的工程能力,可以引入 Celery 做异步任务队列,训练完成后通过 WebSocket 推送通知到前端。你可能会觉得这是过度设计,但在标题里挂了"大数据""深度学习"这些词的情况下,有一个异步任务框架作为支撑,答辩时讲"高并发场景下的任务调度",至少技术上不虚。
6. 答辩演示与系统稳定性:那些没人提醒你的关键细节
6.1 演示环境准备:不要在现场碰运气
毕业设计答辩当天,系统能不能顺畅跑起来,直接影响了评委对你的印象分。我受过一次教训:在教室演示时用的是校园网,结果爬虫模块重新采集数据时被目标网站限流,页面加载图表时数据库查询又因为网络抖动卡了十几秒,场面一度很尴尬。后来我学聪明了,在答辩前做了三件事。
第一,准备一份完整的预采集数据快照。把爬虫采集好的数据导出成一个 SQLite 备份文件,答辩前现场恢复数据库,这样即使网络环境恶劣,系统也能基于本地数据完成所有演示。
第二,提前完成模型预加载。在 Django 启动时就把模型文件载入内存,而不是等用户点击预测时才加载。方法是在 App 的 apps.py 的 ready 方法里做全局变量缓存,或者用 django 的缓存框架。如果不这样,第一次访问预测接口时,磁盘 IO 加模型反序列化会让页面卡顿几秒钟,这体验在答辩时很减分。
第三,写一个一键启动脚本。用 shell 或 bat 脚本统一启动数据库(如果需要)和 Django 服务,确保任何人都能在五分钟内把你的系统跑起来。不要小看这一步,老师如果提出"我来试一下",而你连启动命令都要现场敲半天,印象分会大打折扣。我在项目中提供了一个 start.sh,内部逻辑是先检查 Python 虚拟环境是否存在,不存在就创建并安装依赖,然后执行数据库迁移,最后启动开发服务器。
6.2 准备几个"事故级"问题的应答思路
答辩环节最怕评委问的问题是什么?说实话,不是算法细节,而是"这个系统跟已有的商业产品有什么区别""你的模型是怎么保证可信度的""如果换一个数据源,你的模型还能用吗"这三类开放性问题。
我的回答思路是这样的:首先承认在业务功能的丰富程度上,系统确实不及真实商业产品,但设计的重点在于工程链路的完整性——从数据采集、清洗、存储、分析到建模、部署、可视化的全流程打通,体现的是解决实际问题的综合能力。其次,模型可信度方面,除了基础的评估指标,还可以补充说明训练集和测试集的划分方式确保了数据不泄露,特征重要性分析说明了模型的决策依据。最后,关于换数据源的泛化能力,我的系统在特征工程阶段就刻意减少了强依赖特定字段的处理逻辑,大部分特征是从销量序列和商品基本信息中提取的,换一个相似领域的数据集只需要重新训练模型并替换数据源接口即可,代码层面无需大改。
这些问题如果想现场临场发挥,很容易越答越虚,建议提前把上面的思路写成一份技术说明文档,答辩时随身携带,必要时递给老师看,这会让你整个答辩节奏从容不少。
6.3 代码可维护性:毕业设计里的隐形得分点
最后说说代码规范问题。很多毕业设计交上去,源码结构一团糟——爬虫代码、Django 项目、 Jupyter Notebook 全堆在根目录,模型训练脚本和 Web 项目混在一起。这是非常吃亏的:评阅老师拿到源码的第一印象就差了。
我建议的目录结构是这样:拆成 data(存放原始数据和快照)、spider(爬虫模块)、analysis(数据分析脚本)、ml_model(模型训练与评估)、web(Django 项目)。每个模块内入口文件命名为 main.py 或 run.py,并在 README 里写清楚每个模块的启动步骤和依赖。
代码注释也很关键,但不需要每行都写。你需要在关键的地方做模块级 docstring,说明这段代码的作用、输入输出格式、调用方式、涉及的外部依赖。另外,模型训练脚本里一定要写清楚随机种子、数据划分方式和特征构造函数的输出格式,因为这是整个项目里最容易被追问的部分。
如果你愿意在这个细节上多花一点功夫,还可以给 Django 项目加一个简单的接口文档页面,把每个 API 的请求参数和返回结构用表格列出来。这个工作成本不高,但对系统完整性的提升非常明显。
7. 这套系统的后续扩展思路
做完这个系统之后,我有一个挺深的体会:毕业设计的价值不在于你用了多高级的算法,而在于你能不能把一套完整的技术链路打通。随机森林换成了 XGBoost 也好,爬虫换成了手动 CSV 导入也好,核心思路都没有变——先解决数据问题,再建立分析视角,最后用模型做决策支持。
如果你学有余力,我建议从三个方向向下做扩展。第一个方向是更细粒度的预测,把日销预测改成不同品类单独建模,虽然工作量增大,但精度会明显改善。第二个方向是引入更多数据源,比如把评论情感分析的结果作为特征加入预测模型,文本特征和数值特征的融合会让模型更饱满。第三个方向是把预测系统做成可配置的,让用户自己上传商品数据,系统自动完成特征提取、模型重训练和可视化分析,这就往 SaaS 的方向靠近了,作为毕业论文的延伸价值会非常可观。
但我也得提醒一句:扩展方向可以作为论文的展望章节来写,系统的核心功能一定控制在毕业设计周期内能完成并充分验证的范围。我在实际带学生的过程中,见过太多人因为贪多,最后连主流程都没跑通。把一个闭环做扎实,比做十个半成品要强得多。
动手之前,先把数据源确认好,把环境装好,把一个最简单的页面跑起来——剩下的,就是一步步往前推的问题了。