據(jù)可視化分析系統(tǒng):Django+ECharts+大模型Agent實戰(zhàn))
畢業(yè)設(shè)計年年都在做電商系統(tǒng)但絕大多數(shù)作品停留在了“能登錄、能下單、后臺CRUD”的水平答辯時被老師一問“分析了什么”就卡殼。今天這篇博文完全圍繞Python電商訂單數(shù)據(jù)可視化分析系統(tǒng)展開用 Django 做后端、配合 ECharts 做可視化看板再接入大模型 Agent 實現(xiàn)自然語言查數(shù)把“訂單數(shù)據(jù)”真正變成“決策依據(jù)”。我會從技術(shù)選型、數(shù)據(jù)庫設(shè)計、分析維度、大模型集成、算法優(yōu)化、常見坑位幾個層面完整拆一遍附帶可直接復用的代碼思路和部署建議不管你是準備畢業(yè)設(shè)計還是想在公司內(nèi)部搭一套輕量級數(shù)據(jù)看板都能從里面拿到干貨。1. 項目整體設(shè)計與技術(shù)選型思路1.1 為什么是 Django 而不是 Flask 或 Spring Boot做數(shù)據(jù)分析類系統(tǒng)第一反應是 Flask輕量、靈活、適合單腳本。但真正要把系統(tǒng)做成一個“能演示、能擴展、能寫進論文/答辯PPT”的完整項目Django 的優(yōu)勢就出來了。自帶 Admin 后臺訂單表、商品表、用戶表可以直接在后臺管理演示時不用額外寫管理頁面。ORM 層做復雜查詢很順手按日期聚合、按商品分組統(tǒng)計這類操作比寫原生 SQL 更安全也更好展示給老師看。自帶模板引擎配合 Django REST Framework 可以同時支撐服務端渲染頁面和前端 Ajax 請求。用戶認證、CSRF 防護、分頁組件都是現(xiàn)成的省去自己造輪子的時間。有同學擔心 Django “太重”其實在電商訂單可視化這個業(yè)務場景里重量反而變成了優(yōu)點——項目結(jié)構(gòu)清晰每寫完一個模塊都能對應到框架的一個標準部分答辯時可以很自然地說“這里用了 Django 的 Class-Based View那邊借用了 ORM 的 annotate 做聚合”。這套話術(shù)老師愛聽。1.2 可視化方案選型為什么核心圖表用 ECharts可視化渲染方案市面上主流的幾個我都有試過簡單對比一下就知道為什么最終推薦 ECharts。方案上手難度交互能力圖表豐富度中文文檔推薦場景ECharts低極強超過 60 種圖表完善后臺管理看板、大屏展示Chart.js低一般基礎(chǔ)圖表為主中輕量頁面Plotly中強科學計算類圖表中需要聯(lián)動、縮放的數(shù)據(jù)探索D3.js很高靈活但開發(fā)量大完全自定義中定制化展示效果ECharts 在電商訂單分析里最實用的幾個點折線圖 柱狀圖混合展示每日訂單量和銷售額趨勢視覺直觀答辯加分。餅圖 / 環(huán)形圖展示商品類目銷售占比幾乎零學習成本。**數(shù)據(jù)縮放組件dataZoom**直接支持在圖表中拖拽查看某個時間段這個功能在展示 365 天訂單走勢時尤其好用。異步加載通過 Ajax 從后端接口拿 JSON 數(shù)據(jù)動態(tài) setOption和 Django REST Framework 配合非常順。我不建議在這個項目里強行用 D3.js它的學習曲線會嚴重擠壓你做數(shù)據(jù)分析和大模型集成的時間而畢業(yè)設(shè)計考察的是“完整度”和“分析深度”不是炫技。1.3 大模型、Agent 在項目里的角色定位2025 年了數(shù)據(jù)可視化項目如果一點 AI 能力都不沾答辯競爭力會弱不少。但也不能為了蹭熱點而亂接大模型。這個項目里大模型承擔兩個非常明確的職責自然語言轉(zhuǎn)查詢用戶輸入“上個月銷售額最高的商品是什么”Agent 組件負責解析語義、生成 Django ORM 查詢代碼或 SQL返回結(jié)果并自動渲染成圖表。智能歸因分析當某個指標出現(xiàn)異常波動比如訂單量突然下跌 20%大模型結(jié)合訂單數(shù)據(jù)和商品數(shù)據(jù)給出可能的歸因方向比如“某商品庫存不足導致下架”或“促銷活動結(jié)束”。這里我建議用大模型 API 而不是本地部署大模型。原因是本地部署需要顯卡資源而且把幾十 GB 的模型跑起來之后你們實驗室或筆記本的風扇會教你做人。用 API 的好處是不占用本地資源系統(tǒng)其余部分運行流暢。API 輸出質(zhì)量通常高于本地小模型尤其在 SQL 生成和歸因分析場景??梢噪S時切換不同模型供應商不會被某一個平臺的限制綁死。Agent 的設(shè)計上我推薦用一個簡化的 ReAct 風格結(jié)構(gòu)意圖識別 → 工具調(diào)用查數(shù)據(jù)庫 → 結(jié)果解釋 → 圖表渲染。后面第六章我會把完整流程展開講。2. 數(shù)據(jù)庫設(shè)計與數(shù)據(jù)處理鏈路拆解2.1 訂單相關(guān)模型怎么設(shè)計才合理很多畢業(yè)設(shè)計的一號坑位就是數(shù)據(jù)表設(shè)計得過于簡陋一張 Order 表里恨不得塞進所有字段。你要記住一個原則表結(jié)構(gòu)設(shè)計是為了分析服務的不是為了存數(shù)據(jù)服務的。電商訂單分析系統(tǒng)至少要有四張核心表users 用戶表 products 商品表 orders 訂單表 order_items 訂單明細表Django 里 models.py 的建議結(jié)構(gòu)如下from django.db import models from django.contrib.auth.models import User class Category(models.Model): name models.CharField(max_length50, verbose_name類目名稱) parent models.ForeignKey(self, nullTrue, blankTrue, on_deletemodels.CASCADE) class Product(models.Model): name models.CharField(max_length200, verbose_name商品名稱) category models.ForeignKey(Category, on_deletemodels.CASCADE) price models.DecimalField(max_digits10, decimal_places2, verbose_name售價) cost models.DecimalField(max_digits10, decimal_places2, verbose_name成本) stock models.IntegerField(default0, verbose_name庫存) class Order(models.Model): order_no models.CharField(max_length64, uniqueTrue, verbose_name訂單號) user models.ForeignKey(User, on_deletemodels.CASCADE) status models.CharField(max_length20, verbose_name訂單狀態(tài)) total_amount models.DecimalField(max_digits10, decimal_places2, verbose_name訂單金額) pay_time models.DateTimeField(nullTrue, blankTrue, verbose_name支付時間) created_at models.DateTimeField(auto_now_addTrue, verbose_name下單時間) class OrderItem(models.Model): order models.ForeignKey(Order, related_nameitems, on_deletemodels.CASCADE) product models.ForeignKey(Product, on_deletemodels.CASCADE) quantity models.IntegerField(verbose_name購買數(shù)量) price models.DecimalField(max_digits10, decimal_places2, verbose_name成交單價)幾點經(jīng)驗之談Order和OrderItem必須拆成兩張表。一個用戶可能購買多件商品一件商品也可能出現(xiàn)在多個訂單里這是典型的一對多關(guān)系。如果強行塞在同一張表聚合查詢會痛苦到懷疑人生。total_amount要在下單時就算好并冗余存儲。不要指望每次展示都sum(quantity * price)性能扛不住邏輯也容易出問題。狀態(tài)字段不要用數(shù)字 0/1/2用字符串更直觀。write 代碼時判斷起來舒服別人讀你的代碼也舒服。訂單量不大的情況下user models.ForeignKey(User, ...)直接用 Django 自帶用戶模型沒問題不要過度設(shè)計。2.2 訂單數(shù)據(jù)的清洗與預處理哪些字段最容易被忽略數(shù)據(jù)庫里的原始訂單數(shù)據(jù)肯定不能直接用典型問題包括支付時間為空用戶下單了但沒付款、訂單狀態(tài)重復、商品類目名稱前后不一致比如“手機”和“智能手機”其實是同一個類目。我建議在 Django 里用management command做數(shù)據(jù)清洗而不是寫一次性腳本之后就不管了。python manage.py clean_orders自定義命令的核心步驟1. 剔除支付時間為空的記錄或標記為“未支付” 2. 統(tǒng)一狀態(tài)字段枚舉值例如 pending / paid / shipped / completed / cancelled 3. 商品類目歸一化用正則或映射表處理同義詞 4. 校驗金額確保訂單總金額等于明細金額之和 5. 異常數(shù)據(jù)單獨導出到 exceptions.csv方便追溯有一個非常隱蔽的坑時區(qū)問題。Django 開啟USE_TZ True之后數(shù)據(jù)庫里存的是 UTC 時間如果你的線上用戶都在中國直接按日期分組統(tǒng)計會發(fā)現(xiàn)在每天 8 點前的訂單被算到前一天去了。解決方法是from django.db.models.functions import TruncDate from django.db.models import Sum from django.utils import timezone # 將 UTC 時間轉(zhuǎn)換為北京時間再截斷到日期 order_daily ( Order.objects .filter(statuspaid) .annotate( local_dateTruncDate( timezone.localtime(TruncDate(pay_time)) ) ) .values(local_date) .annotate(totalSum(total_amount)) )實際開發(fā)中更穩(wěn)妥的做法是處理時統(tǒng)一使用固定偏移或者干脆關(guān)閉 USE_TZ僅用本地時間存儲。畢業(yè)設(shè)計演示場景時間一致性比“國際化標準”重要得多。2.3 數(shù)據(jù)分析的核心維度與指標設(shè)計數(shù)據(jù)可視化不能只局限于“看圖表”。一個合格的電商訂單分析系統(tǒng)至少要覆蓋下面幾個維度每個維度都需要計算對應的核心指標。訂單趨勢分析按日/周/月統(tǒng)計訂單量和銷售金額觀察整體走勢、環(huán)比增長率、同比變化。商品銷售分析按商品維度統(tǒng)計銷量、銷售額、毛利率并計算 Top N 爆款商品。類目結(jié)構(gòu)分析各品類銷售額占比、類目下商品數(shù)量分布。用戶行為分析用戶訂單頻次、客單價、復購率、新老用戶占比。區(qū)域分布分析基于用戶收貨地址統(tǒng)計地區(qū)銷售分布用地圖或柱狀圖展示。支付與履約分析未支付訂單占比、配送時長分布、取消訂單原因統(tǒng)計。關(guān)于指標定義有一個容易出錯的地方銷售額是含稅還是不含稅做畢業(yè)設(shè)計可以簡化處理但要在文檔里寫清楚。我更推薦統(tǒng)一使用“實付金額”來統(tǒng)計即剔除退款和取消訂單后的實際收入。后面所有圖表都基于同一套口徑不然會出現(xiàn)折線圖上升但柱狀圖下降的矛盾結(jié)果答辯時會被當場抓住。3. 可視化看板與后端接口的完整實現(xiàn)3.1 Django REST Framework 接口怎么給前端喂數(shù)據(jù)可視化頁面的數(shù)據(jù)來源我統(tǒng)一走 DRF 的 API 接口和前端頁面完全解耦。這樣做的好處是同一個接口網(wǎng)頁看板能用大模型 Agent 也能用未來如果要寫小程序/App后端一行不用改。一個典型的訂單趨勢接口實現(xiàn)如下# views.py from rest_framework.views import APIView from rest_framework.response import Response from django.db.models.functions import TruncDate from django.db.models import Sum, Count from .models import Order class OrderTrendAPIView(APIView): def get(self, request, formatNone): # 按天聚合訂單量和成交金額 daily_data ( Order.objects .filter(statuspaid) .annotate(dayTruncDate(pay_time)) .values(day) .annotate( order_countCount(id), total_salesSum(total_amount) ) .order_by(day) ) days [] order_counts [] sales_amounts [] for item in daily_data: days.append(item[day].strftime(%Y-%m-%d)) order_counts.append(item[order_count]) sales_amounts.append(float(item[total_sales])) return Response({ days: days, order_counts: order_counts, sales_amounts: sales_amounts })注意三個細節(jié)TruncDate(pay_time)可以截斷到天但類型是datetime.date轉(zhuǎn) JSON 前需要strftime格式化否則前端拿到的時間不好處理。float(item[total_sales])必須做類型轉(zhuǎn)換。Django 的DecimalField聚合出來是Decimal類型Django REST Framework 序列化時會出幺蛾子手動轉(zhuǎn)成 float 最保險。接口地址用名詞復數(shù)如/api/orders/trend/不要用動詞保持 RESTful 風格。3.2 ECharts 動態(tài)渲染訂單趨勢看板前端我推薦用原生 HTML JavaScript盡量減少框架依賴。加載 ECharts 的方式直接走 CDN不能聯(lián)網(wǎng)演示的話可以下載 echarts.min.js 放到 static 目錄。訂單趨勢圖的核心邏輯fetch(/api/orders/trend/) .then(response response.json()) .then(data { var myChart echarts.init(document.getElementById(trendChart)); var option { tooltip: { trigger: axis }, legend: { data: [訂單量, 銷售額] }, grid: { left: 10%, right: 5%, top: 15%, bottom: 10% }, toolbox: { feature: { dataZoom: { show: true }, saveAsImage: { show: true } } }, dataZoom: [ { type: inside, start: 0, end: 100 }, { type: slider, start: 0, end: 100 } ], xAxis: { type: category, data: data.days }, yAxis: [ { type: value, name: 訂單量 }, { type: value, name: 銷售額 } ], series: [ { name: 訂單量, type: line, smooth: true, data: data.order_counts }, { name: 銷售額, type: bar, yAxisIndex: 1, data: data.sales_amounts } ] }; myChart.setOption(option); window.addEventListener(resize, () myChart.resize()); });幾個提升演示效果的小技巧雙 Y 軸刻度一定要分開訂單量和銷售額根本不在同一個數(shù)量級共用 Y 軸的話訂單量那條折線會始終趴在地上。smooth: true讓折線更平滑視覺上更有“數(shù)據(jù)分析”的味道。toolbox.saveAsImage導出的圖表圖片可以直接粘貼到論文附錄里答辯時老師問“你的分析依據(jù)是什么”直接甩圖。3.3 數(shù)據(jù)大屏布局的 CSS 網(wǎng)格方案單一圖表頁面太單薄畢業(yè)設(shè)計要往“可視化大屏”的方向靠。我用的方案是 CSS Grid 布局不依賴任何 UI 庫.dashboard-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: auto auto; gap: 16px; padding: 16px; background: #f0f2f5; } .chart-card { background: #ffffff; border-radius: 12px; padding: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); }大屏布局一般可以這樣分配位置內(nèi)容占比第一行左銷售額與訂單量趨勢1/3第一行中類目銷售占比餅圖1/3第一行右Top10 商品排行1/3第二行左區(qū)域銷售分布1/2第二行右用戶復購與客單價分析1/2原則是每個圖表卡片都不要塞得太滿標題 圖表主體 上下留白大屏的高級感主要來自布局節(jié)奏不是來自配色花哨。4. 大模型 Agent 集成從自然語言到 SQL4.1 為什么要用 Agent 而不是直接調(diào) API很多項目接入大模型的方式非常粗暴前端把用戶問題發(fā)給后端后端直接轉(zhuǎn)發(fā)給大模型 API再把返回文本展示到頁面上。這不叫“集成大模型”這叫“套殼”。正確的做法是讓大模型具備調(diào)用工具的能力。當用戶問“最近 7 天哪個商品賣得最好”時大模型本身并不知道數(shù)據(jù)庫里有什么它需要以下過程識別用戶意圖是“查詢類問題”。從數(shù)據(jù)庫 Schema 中選出需要的表orders、order_items、products。生成 Django ORM 聚合查詢代碼或直接生成 SQL。將查詢結(jié)果轉(zhuǎn)換為自然語言回答例如“最近 7 天銷量最高的商品是 Mini 藍牙音箱共售出 328 件銷售額 65272 元”。這就是 Agent 典型的工具調(diào)用模式。我用了一個精簡的流程用戶輸入 → 意圖判斷 → 提取參數(shù)日期范圍、指標 → 生成查詢代碼 → 執(zhí)行查詢 → 校驗結(jié)果 → 生成自然語言回答 → 渲染圖表4.2 大模型生成 Django ORM 查詢的安全控制允許大模型直接生成 SQL 的最大風險是安全比如注入攻擊、訪問了不該訪問的表。我采用了一個折中方案不讓大模型任意生成 SQL而是讓它生成一個結(jié)構(gòu)化的查詢 JSON。{ table: order_items, metric: total_sales, group_by: product__name, order_by: -total_sales, limit: 10, filters: { order__status: paid, order__pay_time__gte: 2025-01-01 } }后端再用一個簡單的解釋器來執(zhí)行這個 JSON絕對不執(zhí)行大模型生成的裸 SQLfrom django.db.models import Sum from .models import OrderItem def execute_agent_query(query_json): qs OrderItem.objects.all() filters query_json.get(filters, {}) for key, value in filters.items(): qs qs.filter(**{key: value}) group_by query_json.get(group_by) metric query_json.get(metric) result ( qs.values(group_by) .annotate( total_salesSum(price) ) .order_by(- metric)[: query_json.get(limit, 10)] ) return list(result)這個方案的好處非常明顯大模型只需要理解 Schema 并輸出 JSON不需要理解 Django ORM 的細節(jié)生成成功率更高。JSON 里每個字段都是白名單校驗過的即使模型輸出錯誤后端也能安全拒絕大多數(shù)情況。同一套 JSON 可以用于圖表渲染和自然語言回答兩端數(shù)據(jù)口徑一致。4.3 完整鏈路里的 Prompt 設(shè)計要點Prompt 是這個項目的靈魂。我用過一個通用模板效果不錯大家可以直接參考你是一個電商數(shù)據(jù)分析助手。數(shù)據(jù)庫中有以下表 - orders: 訂單主表字段包括 order_no, user_id, status, total_amount, pay_time - order_items: 訂單明細表字段包括 order_id, product_id, quantity, price - products: 商品表字段包括 id, name, category_id, price, stock 需要你輸出嚴格的 JSON 格式查詢條件不要輸出 SQL。 要求 1. 只使用上面的字段禁止臆造字段名。 2. 時間條件使用 ISO 格式如 2025-06-01。 3. 如果問題涉及“銷售額”使用 sum(total_amount)涉及“銷量”使用 sum(quantity)。 4. 類別歸入 category_id名稱歸入 product__name。 5. 只輸出 JSON不要附加解釋。 用戶問題{question}有幾個調(diào)參經(jīng)驗temperature 設(shè)為 0.1 或更低生成查詢條件不需要創(chuàng)造性低溫度能顯著降低幻覺率。給出示例few-shot在 Prompt 里附上兩個“問題 → JSON”示例效果比只給規(guī)則好很多。超時和重試機制必須有API 調(diào)用偶爾會超時用openai庫時要設(shè)置timeout30和max_retries2。4.4 Agent 復用同一個后端接口減少集成成本上面說的查詢 Agent 只是用于自然語言查數(shù)電商訂單可視化系統(tǒng)里還有一個更復雜的歸因分析 Agent。當訂單量在某個時間點異常下跌時系統(tǒng)需要先檢測偏移點再觸發(fā) Agent 分析可能的原因。我的實現(xiàn)思路是后端按日聚合訂單量。用三倍標準差法找出異常點|actual - mean| 3 * std即視為異常。將異常點前后的訂單狀態(tài)分布、商品銷售變化、類目占比變化等數(shù)據(jù)拼成一個摘要文本。調(diào)用大模型 API要求它“基于以下數(shù)據(jù)分析可能原因采用因果歸納 商品維度細化”的方式輸出洞察。歸因 Prompt 的示例片段以下是某電商平臺訂單量異常下降時間段的數(shù)據(jù)摘要 - 下降前7天日均訂單量1532下降后3天日均訂單量862 - 商品銷售變化數(shù)碼類下跌32%食品類上漲5% - 未支付訂單占比從8%升至19% 請基于數(shù)據(jù)推測可能原因并列出可驗證的結(jié)論與建議不要漫無目的地羅列。這套流程跑下來你就不只是在“展示數(shù)據(jù)”而是在做真正的智能分析。答辯時這是絕對的亮點。5. 算法優(yōu)化與后端性能實測5.1 ORM 查詢的 N1 問題怎么避免做訂單明細分析時最容易踩的坑是 N1 查詢。簡單解釋一下當你循環(huán)遍歷每個訂單并在循環(huán)體內(nèi)再去查一次商品表100 個訂單就會產(chǎn)生 101 條 SQL性能極差。# 反面例子 orders Order.objects.all() for order in orders: # 每循環(huán)一次查一次 OrderItem for item in order.items.all(): print(item.product.name)正確做法是用select_related和prefetch_relatedorders Order.objects.prefetch_related( items__product ).filter(statuspaid)prefetch_related會先查出所有訂單再一次性查出所有相關(guān)訂單明細和商品總共 3 條 SQL 解決所有問題。數(shù)據(jù)量達到幾千條之后這個優(yōu)化能讓頁面響應時間從幾秒降到幾百毫秒??梢杂?Django Debug Toolbar 來驗證你的查詢次數(shù)。裝完之后在頁面右側(cè)會顯示執(zhí)行了多少條 SQL如果你的列表頁有幾十條 SQL說明 N1 已經(jīng)出現(xiàn)了。5.2 大表聚合查詢選擇在數(shù)據(jù)庫層做還是 Python 層做很多人有個誤區(qū)聚合邏輯全寫在 Python 里比如把所有訂單循環(huán)一遍手動累加金額。這種做法在數(shù)據(jù)量小的時候沒問題但是當你有幾萬條訂單時會把內(nèi)存和 CPU 全部打爆。正確做法是盡量把聚合下推到數(shù)據(jù)庫層場景推薦做法原因按天統(tǒng)計銷售額ORM 的.annotate(dayTruncDate(...)).values(day).annotate(Sum(total_amount))數(shù)據(jù)庫分組快只返回匯總結(jié)果復雜多表聚合用 Django ORM 組合查詢或借助視圖減少網(wǎng)絡傳輸量極大數(shù)據(jù)量考慮使用QuerySet.iterator()分批處理避免內(nèi)存峰值高頻查詢緩存使用 Redis 緩存聚合結(jié)果相同查詢直接命中緩存我實際測試過用 ORM 聚合 10 萬條訂單數(shù)據(jù)的時候數(shù)據(jù)庫層聚合大概耗時 300 毫秒左右而 Python 層循環(huán)可能要 5 秒以上差距是數(shù)量級的。5.3 Redis 緩存可視化接口扛住演示現(xiàn)場的反復刷新演示現(xiàn)場最尷尬的事是什么你每刷新一次頁面后端都要重新計算一次全量聚合老師一邊問問題你一邊等頁面轉(zhuǎn)圈。解決方案把高頻統(tǒng)計接口加入 Redis 緩存。在 Django 里的實現(xiàn)非常簡單from django.core.cache import cache class OrderTrendAPIView(APIView): def get(self, request, formatNone): cache_key order_trend_daily_2025 cached_data cache.get(cache_key) if cached_data is not None: return Response(cached_data) # 原有聚合邏輯 compute_data() data compute_data() cache.set(cache_key, data, timeout60 * 5) return Response(data)緩存有效期我設(shè)為 5 分鐘因為實際項目中數(shù)據(jù)幾乎不會每分鐘變化就算變了5 分鐘后也能自動更新。演示的時候你甚至可以提前把圖表打開然后不斷切換 tab 展示速度非常順暢。5.4 數(shù)據(jù)量更大時的可擴展方向如果你的訂單數(shù)據(jù)量真的很大比如幾十萬幾百萬級Django ORM 的常規(guī)聚合還是會吃力。可以考慮兩個方向預聚合表每天凌晨用腳本把前一天的統(tǒng)計數(shù)據(jù)計算好存到 summary 表里查詢時只讀 summary 表。改用 ClickHouse / Doris 這類列式數(shù)據(jù)庫架構(gòu)上把 Django ORM 的讀操作分流到數(shù)據(jù)倉庫分析查詢性能提升是數(shù)量級的。不過這個對畢業(yè)設(shè)計來說過于重了寫進“未來展望”章節(jié)供討論即可。6. 實操部署與疑難雜癥速查手冊6.1 本地環(huán)境搭建、依賴安裝與項目初始化基礎(chǔ)環(huán)境需要 Python 3.10、Django 4.2建議 4.2 LTS、MySQL 5.7 或 SQLite默認。但我想強調(diào)一點別用 Python 3.7 或更老的版本Django 新版本已經(jīng)不再支持第三方庫的兼容性也會不斷出問題。我建議依賴管理直接上requirements.txtdjango4.2.7 djangorestframework3.14.0 pandas2.0.3 pymysql1.0.2 redis4.5.4 openai1.3.0 python-dateutil2.8.2創(chuàng)建完虛擬環(huán)境后按下面四步走pip install -r requirements.txt python manage.py startapp orders python manage.py startapp dashboard python manage.py startapp ai_agent python manage.py makemigrations python manage.py migrate python manage.py createsuperuser這四步做完你已經(jīng)有一個能跑的 Django 項目了。接下來再執(zhí)行自定義清洗命令導入訂單數(shù)據(jù)python manage.py clean_orders python manage.py import_orders --path ./data/orders.csv6.2 開發(fā)時最常見的五個問題我把近兩年帶學生做這個項目時遇到的高頻問題整理成了一張速查表你們先收藏遇到問題直接對號入座。癥狀原因解決方案頁面加載極慢SQL 查詢次數(shù)幾百條N1 查詢檢查prefetch_related是否用上圖表日期偏移一天時區(qū)問題關(guān)閉 USE_TZ 或統(tǒng)一當?shù)貢r間轉(zhuǎn)換Cannot resolve keyword pay_time in field listORM 查詢字段拼寫錯誤./manage.py shell里查看字段名前端拿到NaNDecimal 類型未轉(zhuǎn)換float()顯式轉(zhuǎn)換ECharts 地圖不顯示geo 數(shù)據(jù)未加載單獨引入對應地圖 JS中文亂碼MySQL 字符集不是 utf8mb4建庫時加CHARACTER SET utf8mb4有一個隱藏很深的坑本地開發(fā)用的 SQLite 換成 MySQL 后字段類型和聚合函數(shù)的語法有差異比如TruncDate在 SQLite 里支持良好但在某些 MySQL 版本上會出現(xiàn)奇怪的報錯。建議盡早就在 MySQL 上開發(fā)別等最后部署時才換數(shù)據(jù)庫。6.3 展示環(huán)境的部署與小屏適配畢業(yè)設(shè)計答辯通常是自帶筆記本但如果要在服務器上部署我推薦最輕量的方式Nginx 托管靜態(tài)文件和反向代理。Gunicorn 啟動 Django 應用。MySQL Redis 各自獨立容器。Nginx 關(guān)鍵配置片段server { listen 80; server_name your-server-ip; location /static/ { alias /var/www/yourproject/static/; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }大家注意一點Django 的DEBUG False時靜態(tài)文件不會自動由 Django 提供必須在settings.py里正確配置STATIC_ROOT并執(zhí)行python manage.py collectstatic6.4 答辯演示時的數(shù)據(jù)與節(jié)奏建議項目技術(shù)全做完之后剩下的一關(guān)就是演示。數(shù)據(jù)量太小看板光禿禿不好看數(shù)據(jù)量太大加載慢。建議的做法是用 Python 腳本生成 3 萬條左右的模擬訂單數(shù)據(jù)覆蓋近一年時間跨度。模擬數(shù)據(jù)要包含的特點有明顯的高峰期比如某平臺的 618、雙 11 前后方便展示趨勢波動。有 3 到 5 個爆款商品集中貢獻 30% 以上的銷售額圖表結(jié)構(gòu)更清晰。有部分未支付和取消訂單這樣各類分析維度才有對比價值。演示順序推薦順序內(nèi)容時間1介紹項目技術(shù)棧和系統(tǒng)架構(gòu)1 分鐘2展示可視化大屏點擊切換圖表2 分鐘3現(xiàn)場輸入自然語言查詢Agent 返回結(jié)果并渲染圖表3 分鐘4展示異常歸因分析結(jié)果2 分鐘5提問與代碼講解2 分鐘不要一上來就講代碼先讓老師看到完整效果引起興趣后再深入細節(jié)。6.5 關(guān)鍵遺留問題與擴展思路這個項目還有一個值得考慮的方向多 Agent 協(xié)作。目前只有一個查詢 Agent 和一個歸因分析 Agent未來可以拆分出更多子 Agent比如“數(shù)據(jù)更新 Agent 負責同步訂單數(shù)據(jù)”“報告生成 Agent 負責定期輸出銷售日報”“異常檢測 Agent 實時監(jiān)控關(guān)鍵指標”。每個 Agent 各自聚焦一件事通過一個協(xié)調(diào)器統(tǒng)一調(diào)度這就是更復雜的智能數(shù)據(jù)分析平臺了。再有一個方向是把靜態(tài)圖表升級為交互式鉆取分析。用戶點擊柱狀圖中的一個柱子可以繼續(xù)下鉆查看該日期每個類目的銷售明細再點擊類目可以查看具體商品列表。ECharts 的events.on(click)完全支持這種交互實現(xiàn)也不難但從演示效果上看非常加分。7. 寫在最后的幾點真實體會前前后后幫人調(diào)過不少次類似的電商數(shù)據(jù)分析系統(tǒng)有一個體會特別深大多數(shù)項目不是死在技術(shù)難而是死在“數(shù)據(jù)整合不起來”。要么訂單數(shù)據(jù)在數(shù)據(jù)庫里沒打通要么可視化頁面和后端接口各寫各的要么大模型 Agent 只是demo版無法真正從數(shù)據(jù)庫拉數(shù)據(jù)。所以這個項目最值得花時間的地方是把數(shù)據(jù)鏈路徹底理順訂單從清洗入庫到聚合接口到前端渲染到 AI 分析整條鏈路走通之后后面往上加什么功能都很快。還有一個建議別把大量時間花在調(diào) CSS 樣式上一個干凈整潔的看板足夠應付答辯把節(jié)省下來的時間用來做 Agent 提示詞優(yōu)化或者多做幾個分析維度性價比高得多。數(shù)據(jù)分析和 AI 能力才是這個項目的真正賣點也是大家后面學習和求職最容易直接用上的技能。希望這篇拆解對你有幫助如果你也在做類似的項目歡迎留言交流實際踩坑。