ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python+Django城市PM2.5空气质量数据可视化毕业设计实战

Python+Django城市PM2.5空气质量数据可视化毕业设计实战 简介面向毕业设计场景的PythonDjango城市PM2.5空气质量可视化分析项目资源包适合计算机相关专业学生完成数据分析类课题、课程设计与毕业答辩准备也可供开发者学习Django框架结合数据可视化开发。包体共64个文件涵盖17个Python源码文件、Django配置文件与HTML模板、24个CSV数据分析结果、SQL数据库脚本及说明文档压缩包大小12.38MB目录结构清晰便于直接部署与二次扩展。目前已有406人学习下载资源完整度高。内容包含北上广成沈五城市六年PM2.5数据、时间序列逐年变化、不同季度逐年数据、一天中不同时段规律以及PM2.5与温度、相对湿度、大气压、露点、风向等要素的关系分析表格并配有数据导入通用脚本、MySQL数据库文件以及登录注册、首页展示等前端页面。下载后可按README指引快速运行直接支撑毕业设计论文撰写、系统演示与功能扩展。1. 用PythonDjango做城市PM2.5空气质量数据可视化毕业设计到底在做什么打开一个名为“PythonDjango城市PM2.5空气质量数据可视化分析源码数据库毕业设计.zip”的压缩包里面通常是一整套能直接跑的B/S架构项目Django后端、MySQL数据库、爬虫或整理好的CSV数据、ECharts图表页面。这类项目的定位很实际——给本科毕设或课程设计用同时覆盖“后端开发”“数据库设计”“数据可视化”三个考核点。如果你正打算把研究方向定在“空气质量数据分析”又不想从零搭框架这个标题能省掉一大半工作量。它能解决的核心问题只有一句话让一组PM2.5历史数据变成可交互的网页图表并且让答辩老师看到完整的“数据采集→入库→查询→前端展示”链路。适合的人群也很明确具备一点Python基础、但没完整做过Web项目的学生以及想快速验证Django数据可视化流程的从业者。下面从项目骨架、数据库设计、图表落地到真实踩坑把这条链路完整拆开讲。2. 拆解项目骨架从建Django工程到跑通第一个页面这类源码包解压后先别急着双击runserver。你需要先弄清楚文件结构再决定是直接复现还是改造成自己的项目。一个典型的Django毕设工程无论标题怎么写骨架都逃不开下面这些部分。2.1 解压后先看什么源码包里的典型Django工程结构拿到压缩包解压后先看根目录。常见做法是里面有一个主项目目录比如airquality、一个或多个应用目录比如dataapp、visual、一个manage.py外加requirements.txt或db.sqlite3这样的库文件。结构大致是project_root/ ├── manage.py ├── requirements.txt ├── db.sqlite3 # 或数据导入脚本 ├── airquality/ │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── dataapp/ │ ├── models.py │ ├── views.py │ ├── urls.py │ └── migrations/ ├── static/ │ ├── css/ │ ├── js/ # echarts.min.js 通常在这里 │ └── data/ # 原始CSV也可能放这 ├── templates/ │ └── index.html └── 数据导入脚本.py # pandas清洗入库脚本看结构时要重点确认三件事项目依赖是否齐全、数据库是用SQLite还是MySQL、可视化用的是ECharts还是其他库。如果settings.py里配置了MySQL而你的机器上没装那么直接跑必然报2059或2003连接错误。我习惯先把requirements.txt打开看里面的版本号有没有明显冲突比如Django2.2配Python 3.10这一对组合经常会因为pytz兼容性翻车。2.2 环境搭建与依赖安装python安装与虚拟环境怎么做不管你是要复现这个毕设还是照标题重写一个第一步永远是隔离环境。在Django项目上我一般避免用全局Python环境因为不同毕设的Django版本差异很大全局环境下装一个版本后另一个项目就跑不了了。# 创建虚拟环境python版本建议3.8-3.10避开3.12的兼容坑 python -m venv venv # 激活虚拟环境 # Windows下 venv\Scripts\activate # Linux/Mac下 source venv/bin/activate # 安装核心依赖 pip install Django4.2.16 pip install pymysql mysqlclient pandas pip install django-echarts # 这个库不是必须的只是封装了图表组件这里的参数值得多说几句。Django版本我选4.2而不是5.x因为4.2是长期支持版本网上能找到的踩坑资料最多许多毕设源码包的写法比如USE_DEPRECATED_PYTZ、ugettext_lazy在5.x里已经报错。mysqlclient在Windows安装容易报错我通常直接用pymysql然后在__init__.py里做兼容。安装完后验证一下Django是否正常python -c import django; print(django.get_version())如果输出4.2.16说明基础环境到位。这一步不用着急后面每跑一个模块都会回过来检查环境。2.3 创建Django工程和应用django-admin与manage.py的职责边界如果是自己新建项目用django-admin startproject建工程再用python manage.py startapp建应用如果只是复现源码包这两步可以跳过但你要知道它们的作用。django-admin负责全局初始化manage.py负责当前项目的运行级操作两者的边界不能搞混。# 新建工程如果是从头开始 django-admin startproject airquality # 在工程根目录下新建应用 python manage.py startapp dataapp # 在 dataapp/views.py 里先写一个测试视图测试视图先不涉及数据只返回一个HttpResponse确认路由通路是通的。然后在airquality/urls.py里注册from django.contrib import admin from django.urls import path, include urlpatterns [ path(admin/, admin.site.urls), path(, include(dataapp.urls)), # 把应用路由挂到根路径 ]再到dataapp/urls.pyfrom django.urls import path from . import views urlpatterns [ path(, views.index, nameindex), ]这里要注意一个新手常见错误include(dataapp.urls)之前必须已经建好dataapp/urls.py文件否则会报ModuleNotFoundError。我一般会顺手把settings.py里的INSTALLED_APPS加上dataapp不然后面迁移数据库时模型表根本建不出来。跑通第一个页面后项目骨架就算立起来了。接下来第二步也是整个项目的地基数据落地。3. 空气质量数据落库模型设计、ORM查询与数据库初始化PM2.5可视化项目的数据层是整个系统最容易被小看的部分。很多毕设重前端、轻后端图做得花哨一问数据怎么来的、怎么存的答不上来这在答辩时很吃亏。数据这一章要搞清楚三件事数据源长什么样、表结构怎么设计、查询怎么组织。3.1 PM2.5数据从哪来、清洗到什么程度能入库这个毕设标题里没有明确写数据来自哪里所以需要按最常见的方案准备。常规途径有三个中国环境监测总站的历史数据、Kaggle上的全球空气质量数据集、自己写爬虫抓天气网站。毕业设计一般用前两种因为数据量大、字段完整、有权威性。拿到原始CSV后先做一轮清洗入库前的数据至少要满足没有空行、时间字段统一成%Y-%m-%d %H:%M:%S、地名字段统一不能出现“北京”和“北京市”混着写、PM2.5浓度值不为负数。一个简单的清洗脚本长这样import pandas as pd # 读取原始CSV df pd.read_csv(raw_pm25.csv, encodingutf-8-sig) # 处理缺失值PM2.5列为空的行直接删除别用0填充 df df.dropna(subset[pm25]) # 统一时间格式 df[time] pd.to_datetime(df[time], format%Y-%m-%d %H:%M:%S) # 统一城市名避免北京市和北京共存 df[city] df[city].str.replace(市, ) # 过滤异常负值 df df[df[pm25] 0] # 输出清洗后的状态统计 print(f数据总量: {len(df)} 条) print(f时间范围: {df[time].min()} 到 {df[time].max()}) print(f涉及城市: {df[city].nunique()} 个)清洗这一步的取舍要说明白PM2.5浓度缺失的行我直接删除而不用均值填充因为空气质量数据的缺失往往集中在某一段时间用均值填充会人为制造“虚假平稳”可视化出来的曲线反而失真。时间格式统一成datetime64是为了后面在Django ORM里用__gte、__lte做时间范围查询时不踩字符串比较的坑。3.2 数据库建模Django ORM里的三层表结构设计数据库设计不一定要复杂但一定要能自圆其说。这个项目的表结构我见过的多数毕设是三层城市表、监测站点表可选、空气数据表。城市表和站点表是为了回答“某个城市的PM2.5来自哪些站点”这个问题空气数据表存的是逐小时或逐日监测值。以两张核心表为例# dataapp/models.py from django.db import models class City(models.Model): 城市维度表 name models.CharField(max_length64, uniqueTrue, verbose_name城市名称) province models.CharField(max_length64, blankTrue, verbose_name所属省份) longitude models.FloatField(nullTrue, blankTrue, verbose_name经度) latitude models.FloatField(nullTrue, blankTrue, verbose_name纬度) class Meta: db_table dim_city verbose_name 城市 ordering [id] def __str__(self): return self.name class AirQuality(models.Model): PM2.5逐时监测数据表 city models.ForeignKey(City, on_deletemodels.CASCADE, related_nameair_data) monitor_time models.DateTimeField(db_indexTrue, verbose_name监测时间) pm25 models.FloatField(nullTrue, verbose_namePM2.5浓度(μg/m³)) pm10 models.FloatField(nullTrue, verbose_namePM10浓度(μg/m³)) so2 models.FloatField(nullTrue, verbose_nameSO2浓度) no2 models.FloatField(nullTrue, verbose_nameNO2浓度) co models.FloatField(nullTrue, verbose_nameCO浓度) o3 models.FloatField(nullTrue, verbose_nameO3浓度) class Meta: db_table fact_air_quality verbose_name 空气质量监测数据 ordering [monitor_time] # 联合唯一索引同一城市同一时间只保留一条记录 constraints [ models.UniqueConstraint(fields[city, monitor_time], nameuniq_city_time) ] def __str__(self): return f{self.city.name} {self.monitor_time} PM2.5: {self.pm25}这段代码里有三个选择值得说明。第一city字段用了外键而不是直接存城市名是为了ORM聚合查询更顺手比如values(city__name).annotate(avg_pm25Avg(pm25))。第二monitor_time加了db_indexTrue因为可视化的时间范围查询非常频繁没有索引的话百万行数据上做filter(monitor_time__range...)会明显卡顿。第三联合唯一约束是防重复导入的后悔药跑数据导入脚本时如果CSV里有重叠时间段不会把库搞脏。3.3 把CSV灌进MySQLpandas清洗与bulk_create批量入库模型建好后执行迁移python manage.py makemigrations dataapp python manage.py migrate接着把清洗好的CSV导入MySQL。很多人会一条条for循环去create数据量小还好到几万条就慢得受不了。我一般用bulk_create配合pandas的iterrows一次批量提交。# 导入脚本import_data.py import os import django import pandas as pd from datetime import datetime # 手动初始化Django环境否则单独跑不了ORM os.environ.setdefault(DJANGO_SETTINGS_MODULE, airquality.settings) django.setup() from dataapp.models import City, AirQuality def import_csv_to_db(csv_path): # 读取清洗好的CSV df pd.read_csv(csv_path, encodingutf-8-sig) df[monitor_time] pd.to_datetime(df[monitor_time]) # 城市维度表先灌入获取城市ID与对象映射 city_map {} for city_name in df[city].unique(): city_obj, _ City.objects.get_or_create(namecity_name) city_map[city_name] city_obj # 批量组装ORM对象 batch [] batch_size 2000 for idx, row in df.iterrows(): batch.append(AirQuality( citycity_map[row[city]], monitor_timerow[monitor_time].to_pydatetime(), pm25row.get(pm25), pm10row.get(pm10), so2row.get(so2), no2row.get(no2), corow.get(co), o3row.get(o3), )) # 攒够一个批次就提交一次避免内存爆炸 if len(batch) batch_size: AirQuality.objects.bulk_create(batch, ignore_conflictsTrue) batch.clear() print(f已导入 {idx 1} 条记录) # 最后一批别忘了提交 if batch: AirQuality.objects.bulk_create(batch, ignore_conflictsTrue) print(f导入完成总数{AirQuality.objects.count()}) if __name__ __main__: import_csv_to_db(cleaned_pm25.csv)bulk_create里的ignore_conflictsTrue参数很关键它利用前面模型里的联合唯一约束让重复时间段的记录被直接跳过而不是报错。不加这个参数数据稍有重叠整个脚本就会中断这类坑在毕设中被反复踩。3.4 ORM查询套路按城市、按时间、按污染等级聚合数据进去了但图表不会直接认ORM对象它认的是JSON。所以视图层要做的事就是把数据库里的记录转换成“图表消费”的结构。常见的聚合场景有三个。查某城市全年的PM2.5日均值from django.db.models import Avg, Max, Min from django.db.models.functions import TruncDate # 按天聚合取日均值、最大值和最小值 daily_stats ( AirQuality.objects .filter(city__name北京, monitor_time__year2024) .annotate(dateTruncDate(monitor_time)) .values(date) .annotate( avg_pm25Avg(pm25), max_pm25Max(pm25), min_pm25Min(pm25), ) .order_by(date) )查污染等级分布用 Case/When 把数值映射成等级from django.db.models import Case, When, Value, IntegerField # 按国标把PM2.5浓度划分为优、良、轻度、中度和重度 level_case Case( When(pm25__lt35, thenValue(优)), When(pm25__lt75, thenValue(良)), When(pm25__lt115, thenValue(轻度污染)), When(pm25__lt150, thenValue(中度污染)), When(pm25__lt250, thenValue(重度污染)), defaultValue(严重污染), output_fieldIntegerField(), )注意这里的When(pm25__lt35, thenValue(优))顺序不能颠倒Django的Case是按书写顺序匹配的如果把“重度污染”写在前面后面的分支永远不会被命中。这是新手最容易懵的地方。4. 可视化图表与服务端渲染ECharts怎么和数据接口对接数据模型和查询准备好了下一步就是把它变成浏览器里能看到的折线图和柱状图。可视化是这个项目最出彩的部分也是最容易在答辩现场翻车的部分——图出不来、数据对不上、图表一片空白都是高频问题。4.1 选型为什么毕设用Django模板ECharts而不是前后端分离做数据可视化可以选前端框架Vue/React加后端API也可以选Django模板加ECharts。对于毕业设计我一般建议后者。理由很现实毕设的验收标准往往是“功能完整、能跑、能讲清楚”一个前后端分离项目需要额外处理跨域、路由配置、打包构建任何一个环节出错都可能阻塞整条链路而Django模板渲染只需要一个render函数就能把页面交出去。另一个原因在答辩时的说辞上“模板渲染”对应的是服务端渲染你可以明确地讲出数据流浏览器发起请求 → Django视图查询MySQL → 模板变量注入HTML → ECharts读取变量画图。前后端分离则要被追问前端怎么部署的、接口鉴权怎么做、为什么不在一个工程里完成。提问空间变大风险也随之变大。ECharts在data visualization领域的地位不多说它的优势是图表种类丰富、中文文档全、甚至不需要npm直接下载一个echarts.min.js放进静态目录即可。对毕设来说这种低成本接入方式非常友好。4.2 让Django吐出JSONREST接口与时间序列序列化如果模板里要放图表数据有两个做法一是把数据塞进模板变量在JavaScript里读取二是单独开一个JSON接口页面加载后用fetch取数据。两者我都用过更推荐第二种因为折线图需要随筛选条件动态更新固定模板变量做不到。先加一个JSON接口返回指定城市的PM2.5时间序列# dataapp/views.py import json from datetime import datetime from django.http import JsonResponse from django.db.models import Avg from django.db.models.functions import TruncHour from .models import AirQuality def api_pm25_trend(request): 返回指定城市24小时PM2.5变化趋势的JSON接口 city_name request.GET.get(city, 北京) date_str request.GET.get(date, 2024-12-01) # 前端传了筛选日期这里转成datetime范围 target_date datetime.strptime(date_str, %Y-%m-%d) # 按小时聚合PM2.5均值 hourly ( AirQuality.objects .filter(city__namecity_name, monitor_time__datetarget_date.date()) .annotate(hourTruncHour(monitor_time)) .values(hour) .annotate(avg_pm25Avg(pm25)) .order_by(hour) ) # datetime无法直接JSON序列化手动转成字符串 result { city: city_name, date: date_str, hours: [item[hour].strftime(%H:%M) for item in hourly], values: [round(item[avg_pm25], 1) for item in hourly], } return JsonResponse(result, safeFalse)接口里最容易被忽略的是时间序列化。TruncHour返回的是datetime对象直接放进去会报Object of type datetime is not JSON serializable所以我会显式调用strftime(%H:%M)。这是一个典型的“跑起来才知道”的坑代码写的时候编译器不会提示任何错误。然后在dataapp/urls.py里挂上urlpatterns [ path(, views.index, nameindex), path(api/pm25-trend/, views.api_pm25_trend, nameapi_pm25_trend), ]4.3 ECharts画PM2.5折线图从静态文件引入到图表初始化模板页面里把echarts.min.js放在static/js/目录下然后加载模板变量和接口数据。这里有一个关键配置容易漏掉settings.py里的STATICFILES_DIRS。# airquality/settings.py STATIC_URL /static/ STATICFILES_DIRS [ BASE_DIR / static, # 项目根目录下的static文件夹 ]不配STATICFILES_DIRS模板里的{% load static %}标签就会找不到echarts.min.js页面会报404。这个问题在Django 3.2之后尤其多见因为新增了staticfiles的严格路径检查。模板页面templates/index.html的核心部分{% load static %} !DOCTYPE html html langzh-CN head meta charsetUTF-8 title城市PM2.5空气质量数据可视化/title style #chart { width: 95%; height: 520px; margin: 0 auto; } /style /head body div idchart/div !-- 引入本地的ECharts不用CDN答辩现场断网也能演示 -- script src{% static js/echarts.min.js %}/script script // 初始化图表容器 var chart echarts.init(document.getElementById(chart)); // 从JSON接口拉取数据 fetch(/api/pm25-trend/?city北京date2024-12-01) .then(response response.json()) .then(data { // 设置图表配置项 chart.setOption({ title: { text: data.city data.date PM2.5变化趋势 }, tooltip: { trigger: axis }, xAxis: { type: category, data: data.hours }, yAxis: { type: value, name: μg/m³ }, series: [{ name: PM2.5, type: line, data: data.values, smooth: true, // 平滑曲线 areaStyle: { opacity: 0.2 } }] }); }); /script /body /html这里有两个参数值得注意。smooth: true让折线变成平滑的曲线视觉上更专业areaStyle给曲线下方加渐变阴影这两个细节在答辩演示时能明显提升观感。另一个被问得最多的点是“为什么用fetch而不是axios”——答案很简单项目里没有node.js环境fetch是浏览器原生API不需要引入额外依赖也避免了跨域问题因为它们同源。5. 毕设项目避坑数据库乱码、图表空白、静态文件404等6个常见问题这个是源码包复现环节里最值得写的一段很多项目跑不起来不是代码逻辑错而是环境细节没对齐。以下几条踩坑记录每一条都是我在实际项目中付出过时间代价的。5.1 现象页面显示“?”或乱码数据库中中文全是问号原因几乎可以断定是MySQL建库字符集不对。很多人用默认的utf8mb4_general_ci之外的老字符集或者直接在命令行创建数据库时不指定字符集。解决办法是在settings.py里配置连接参数同时在建库时明确字符集DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: airquality_db, USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, }, } }注意OPTIONS里的charset要和MySQL服务端一致。如果数据库已经建好了可以在MySQL命令行执行ALTER DATABASE airquality_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;来补救。5.2 现象页面表格正常但ECharts图画出来是空白先别怀疑JavaScript代码九成是容器高度问题。ECharts的容器div如果高度是0或者没有被渲染图表会自动显示空白。很多人写在style里的height: 520px是对的但如果这个div被CSS类的display: none影响或者父级容器高度塌陷图表同样初始化失败。解决方法是初始化前检查容器尺寸var chartDom document.getElementById(chart); // 如果获取不到高度强制设置 if (chartDom.offsetHeight 0) { chartDom.style.height 520px; } var chart echarts.init(chartDom);5.3 现象页面样式加载了但echarts.min.js报404静态文件404的原因十有八九是STATICFILES_DIRS配错或没配。Django的runserver在调试模式下确实会接管静态文件但它只会找app/static/和STATICFILES_DIRS路径下的文件。如果项目里把echarts.min.js放在根目录static/js下而settings.py没加BASE_DIR / static就必然404。注意STATIC_ROOT和STATICFILES_DIRS的区别前者是collectstatic收集到的部署目录后者是开发时的源目录两个指向同一个路径会导致django.core.management.CommandError。5.4 现象数据导入后图表显示的时间偏移了8小时这是一个非常隐蔽的坑。Django的settings.py里默认TIME_ZONE UTC而本地数据是东八区。如果你在USE_TZ True状态下直接把本地时间字符串写入DateTimeFieldDjango会把它按UTC存再读出来时API返回的也是UTC时间前端画图就会整体偏移8小时。解决这个问题我习惯把所有时间统一按本地时间处理并且查询时显式忽略时区USE_TZ False # 对单机毕设项目直接关掉时区转换最省心 TIME_ZONE Asia/Shanghai如果你的源码包参数里USE_TZ True且数据已经入库不用重导查询时用extra或直接在SQL里做时间转换。最简单的方式是把已有数据重新清洗一遍避免后续所有接口都带着8小时误差。5.5 现象CSV里有100万行bulk_create跑了一个小时还没完原因很简单单批次数据量太大或批次内跨表外键查询太频繁。我见过把batch_size设为10万的做法这在内存紧张的笔记本上会直接造成MemoryError而且单次SQL语句过长会被MySQL拒绝。稳妥的批次大小是2000到3000同时在导入时不要执行任何save()之外的查询比如不要在循环里用City.objects.filter(...).first()。正确做法是像之前代码里那样先把所有城市一次性映射成字典内存消耗可控速度能提升几十倍。5.6 现象本地运行正常部署到云服务器后admin后台样式全没了本地调试时runserver会代管静态文件但上线后 Nginx 不再有这个能力必须执行collectstatic。在settings.py里配置好STATIC_ROOT后python manage.py collectstatic --noinput然后让Nginx把/static/路径指到STATIC_ROOT目录。这一条不算毕设必答但如果你的项目要在线演示这几乎是躲不开的一步。6. 让项目从“能跑”变成“能答辩”性能优化与功能扩展的几个技巧到了这一步项目已经能跑通但还停留在“教材级”水平。要让它脱离通用教程的阴影就需要在性能和交互上做出亮点以下这两个方向值得投入。6.1 用annotate把24小时均值聚合放到数据库端如果在页面里要展示“全年各城市PM2.5年均值排行”最容易想到的是把所有记录查出来然后Python端循环计算这是性能上的黑匣子数据量一大就卡。我通常直接让数据库完成聚合from django.db.models import Avg from django.db.models.functions import TruncYear # 按城市年份聚合直接生成排名数据 city_rank ( AirQuality.objects .annotate(yearTruncYear(monitor_time)) .values(year, city__name) .annotate(avg_pm25Avg(pm25)) .order_by(-avg_pm25) .values(year, city__name, avg_pm25) )这样返回的数据直接能喂给ECharts的柱状图而且SQL在数据库端执行效率比Python循环高一个数量级。需要注意的是TruncYear会返回整年datetime在前端要再取.year属性。6.2 时间刷选器的实现思路选好时间范围再画图几乎每个答辩评委都会关心交互设计。时间刷选不用引入日期控件库直接用HTMLinput typedate加一个“更新”按钮JS读取值后重新fetch接口即可。接口里接收start_date和end_date两个参数ORM里用monitor_time__range过滤start request.GET.get(start_date) end request.GET.get(end_date, start) # 加一天把end闭区间转成半开区间查询 end_dt datetime.strptime(end, %Y-%m-%d) timedelta(days1) data AirQuality.objects.filter(monitor_time__range(start, end_dt))这里加一天的跨度是折线图按日查询时非常容易犯的错误SQL的range是闭区间直接传2024-12-01到2024-12-31会漏掉31号当天0点之后的所有数据。6.3 导出CSV验证正确性的价值答辩评委可能会问“你的数据准确吗”这时候一张可导出的CSV远比页面上的图表有说服力。用Django的StreamingHttpResponse导出现有查询结果是顺手加上的功能import csv from django.http import StreamingHttpResponse def export_csv(request): response StreamingHttpResponse(content_typetext/csv) response[Content-Disposition] attachment; filenamepm25_export.csv writer csv.writer(response) writer.writerow([城市, 时间, PM2.5]) for row in AirQuality.objects.values_list(city__name, monitor_time, pm25)[:5000]: writer.writerow(row) return response这里有个值得说的细节我用StreamingHttpResponse而不是HttpResponse是因为大数据量下前者不会把所有行一次性加载到内存而这个优势在答辩现场口头讲出来比放在PPT里更真实。做完这些项目就不再是“抄来的毕设”每一处改动你都能说清楚动机。我自己的习惯是每改完一个功能就用git init建一个本地仓库提交信息写清楚“加了时间筛选接口”“修复时区偏移”这样即使某次改挂了也有后悔药可吃。最后真心说一句毕业设计更重要的是让链路完整、逻辑自洽把这些坑避开你的项目就已经比大多数同题目的作品扎实了希望帮到你。本文还有配套的精品资源点击获取
返回列表