news 2026/9/16 16:11:19

基于Python和Django的高考志愿填报系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Python和Django的高考志愿填报系统设计与实现

简介:这套基于Python+Django的高考志愿填报系统,是面向计算机相关专业学生的高分毕业设计资料包,适用于毕业设计、课程设计或项目初期立项演示。资源包含完整的系统源码、数据库脚本及详细设计文档,覆盖考生信息管理、志愿智能推荐、院校专业查询等核心业务模块,适合希望快速搭建完整项目并理解Django框架实际开发流程的读者。压缩包大小约214MB,目前已有125人学习下载。资料按功能模块组织,包含项目代码、数据库文件、设计说明文档等,代码已在Windows与Mac环境下测试通过,可直接运行或二次开发;同时附带答辩所需的系统架构说明、流程设计等内容,能帮助使用者节省从零搭建的时间,高效完成课设或毕设任务。该资源特别适合软件工程、人工智能、电子信息等专业学生进阶学习或作为项目参考,也方便入门者通过完整案例掌握前后端交互与数据库设计的要点。

1. 从志愿草表到 Web 应用:Python + Django 高考志愿填报系统要解决的核心问题

高考出分后那几天,考生和家长面对的不是一张表,而是几百页招生计划、多批次选科限制、各校历年录取分数与位次的组合判断。基于 Python 与 Django 的高考志愿填报系统,把这些数据拆解成院校库、专业库、招生计划、历年录取线和考生自己的志愿草表,让筛选、排序、保存、修改都在浏览器里完成。前台考生可以按选科组合和位次区间检索可报院校,后台维护招生计划与分数线数据,也支持用 Excel 批量导入每年更新的计划。压缩包里还带了数据库文件、详细设计文档和管理端配置,适合软件工程、计科、人工智能等专业学生做课程设计或毕业设计二次开发。拿到项目后,第一步不是跑代码,而是先看数据库设计。

2. 数据表设计是整套系统的主干:院校、专业、招生计划与历年录取线

接手一个 Django 毕设项目时,我习惯先翻 models.py 而不是先跑页面。数据表的设计直接决定了后台管理页能提供哪些筛选条件、推荐逻辑好不好写、Excel 导入脚本要处理哪些字段。这套系统里的表关系不复杂,但把每一张表的定位说清楚,后续调推荐算法时就不用反复改表结构。

2.1 从一张 ER 图说起:六张核心表如何关联

围绕志愿填报业务,核心实体可以归纳成六类:用户、学生档案、院校、专业、招生计划、历年录取线,另外再用一张志愿表保存用户的推荐结果和手动调整。用户与学生档案可以拆成两张表,常见做法是用 Django 内置的 User 认证体系,再通过 OneToOneField 挂一个学生资料表,这样登录注册直接复用 Django 自带能力,又能扩展选科、成绩、位次这些字段。

院校和专业属于基础数据,它们本身不产生志愿记录。真正被志愿记录引用的是“招生计划”:某一年、某一个批次、某所学校的某个专业计划招多少人、选科要求是什么。招生计划是推荐逻辑检索的主体,而历年录取线因为需要按年份重复存储,单独建一张外键关联表,结构更干净。

2.2 物理表与 Django ORM 的对应关系及模型代码

把压缩包里的 models.py 核心部分压缩后,表关系大概长这样:

class School(models.Model): code = models.CharField("院校代码", max_length=20, db_index=True) name = models.CharField("院校名称", max_length=100, unique=True) province = models.CharField("所在省份", max_length=30) level = models.CharField("办学层次", max_length=20, choices=[("985", "985"), ("211", "211"), ("双一流", "双一流"), ("普通本科", "普通本科")]) nature = models.CharField("办学性质", max_length=10, choices=[("公办", "公办"), ("民办", "民办")]) class RecruitPlan(models.Model): school = models.ForeignKey(School, on_delete=models.CASCADE, related_name="plans") major = models.ForeignKey(Major, on_delete=models.CASCADE, related_name="plans") year = models.IntegerField("招生年份", db_index=True) batch = models.CharField("批次", max_length=20, choices=[("本科批", "本科批"), ("专科批", "专科批"), ("提前批", "提前批")]) plan_num = models.IntegerField("计划人数") subject_req = models.CharField("选科要求", max_length=50) class ScoreLine(models.Model): plan = models.ForeignKey(RecruitPlan, on_delete=models.CASCADE, related_name="scorelines") year = models.IntegerField("录取年份") min_score = models.IntegerField("最低分", null=True, blank=True) min_rank = models.IntegerField("最低位次", null=True, blank=True) avg_score = models.IntegerField("平均分", null=True, blank=True)

代码里有两个关键设计。第一,School.code 加了 db_index=True 并且作为逻辑查询主键,Excel 导入时靠院校代码去重,比直接用 name 查询更可靠,也能抗住院校改名的干扰。第二,RecruitPlan 和 ScoreLine 拆成两张表,是因为同一个专业的招生计划每年都在变化,而历年分数线要跨年份做聚合查询,单独存放后 ORM 里的 annotate、filter 都能直接作用于 year 字段。

2.3 历年分数线单独建表的取舍

常见误区是把近三年最低分直接拼成一个字符串存进招生计划表,比如存成“2023:580|2024:575”。这种方案在页面展示上确实直观,但一旦要做“近三年最低位次都在当前位次之前”这样的跨年份比较,就得在应用层切字符串,又慢又容易错。拆分成 ScoreLine 表后,一次外键反向查询就能拿到所有历史记录,后台管理里也能对每一年的数据单独编辑。

另一个取舍是同时保留分数和位次。分数受当年试题难度影响,参考价值有限;位次直接反映考生在全省考生中的排位。原始表里如果只有分数,建议在导入历史数据时按当年一分一段表补上 bit次 字段,后续推荐算法能直接用位次做比较。

2.4 字段设计里容易踩的坑

设计表的时候就应该把可能出现的脏数据挡在门外,下面这几个位置我在实际运行中经常看到问题:

位置常见问题建议
选科要求存成“物理或化学”自由文本统一成“物理+化学”“物理或化学”或 JSON 数组,写入前清洗
年份用字符串存导致排序异常用 IntegerField,查询时带 year 条件
计划人数用 CharField 存储IntegerField,Excel 导入时把 NaN 处理成 0
历年分数空值填 0用 null=True,不要填 0,否则筛选 min_score 会误伤

选科要求的清洗要特别说。各省新高考规则不一样,有的要求“物理必选”,有的要求“物理和化学均选”,有的是“政治或地理任选一门”。如果原始表里是自由文本,最好在导入阶段做一个映射,把中文描述替换成带操作符的代码,推荐逻辑里写一个解析函数去匹配,而不是靠字符串 contains 碰运气。

2.5 建库迁移与初始数据导入命令

数据库文件通常放在压缩包的 database 目录下,可能是 .sql 文件,也可能是 Django fixture。先用命令把表结构建出来,再决定导入哪种初始数据:

python manage.py makemigrations python manage.py migrate python manage.py createsuperuser python manage.py loaddata initial_data.json

makemigrations 负责根据 models.py 生成迁移脚本,migrate 把表结构写入实际数据库,createsuperuser 创建的后台账号会进到 Django 默认的 User 表。如果提供的是 .sql 文件,可以在数据库管理工具里直接执行;如果提供的是 fixture,loaddata 一次还原完整数据。导入完成后建议用下面的命令验证数据条数:

python manage.py shell -c "from 业务app.models import RecruitPlan; print(RecruitPlan.objects.count())"

3. 选科匹配、位次换算与冲稳保推荐:核心业务逻辑的 Django 实现

数据表就绪后,系统的核心价值集中在推荐逻辑上。志愿填报推荐和电商推荐不同,它不需要猜用户偏好,而是必须严格服从约束:选科组合不满足的专业不能显示,考生位次与院校历年录取位次差距过大的专业不能乱推荐。

3.1 先按选科和批次把招生计划筛掉一半

选科匹配是第一道门槛。假设考生选科组合是“物理+化学+生物”,表单提交后把科目按约定传到后端,Django 视图里可以这样过滤:

def filter_by_subject(queryset, subjects, batch, year): q = Q(year=year) & Q(batch=batch) for subject in subjects: q &= Q(subject_req__icontains=subject) return queryset.filter(q)

这段代码用 icontains 做包含匹配,适合科目要求还是自由文本的原始数据,但边界很清楚:如果一条计划要求“物理或历史”,用 AND 逻辑会把符合条件的计划排除掉。所以我通常先把 subject_req 清洗成统一格式,必选用物理+化学,任选用[物理,化学],再写一个解析函数处理两种操作符,避免无脑 contains。

3.2 位次换算的原理:为什么比单纯看分数更接近真实

分数线的价值在于映射到省排名。同样是 580 分,2022 年可能排在全省 2 万名,2024 年可能已经是 2.8 万名,直接用分数对比招生计划里的最低分,结论会偏差很大。位次换算的做法是:取目标专业近三年的最低位次,比如得到 21000、19500、22000,再和考生今年的位次做相对比较。

没有完整一分一段表时,可以用简化版:把考生位次和历年最低位次的相对差值作为排序指标,差值越小代表该专业往年门槛越高。这个相对差值就是下一节冲稳保分档的核心参数。

3.3 冲稳保三档划分与参数表

冲稳保是考生真正关心的输出结果。常见做法是把“考生位次”和“院校专业近年最低位次”做差值比例,按区间分类:

档位ratio 区间使用场景
ratio < -0.15院校历年录取位次明显好于考生位次,风险高
-0.15 到 0.15位次接近,录取概率中等
ratio > 0.15院校历年录取位次明显差于考生位次,托底用

ratio 的计算方式是(院校近年最低位次 - 考生位次) / 考生位次。考生位次数值越小排名越靠前,所以 ratio 为负数说明院校门槛比考生位次高,属于冲刺。这个阈值不是固定的,不同批次可以调:提前批可以收紧到 0.1,本科批保持 0.15 能多留出候选。

3.4 View 层推荐逻辑的代码骨架

下面这段代码是推荐引擎的核心骨架,放在 views.py 里就能工作:

def build_recommendations(student_rank, subjects, batch, year): from django.db.models import Max base_qs = RecruitPlan.objects.filter(year=year, batch=batch) base_qs = filter_by_subject(base_qs, subjects, batch, year) recommendations = [] for plan in base_qs: lines = plan.scorelines.filter(year__gte=year - 3) if not lines.exists(): continue ref_rank = lines.aggregate(Max("min_rank"))["min_rank__max"] if not ref_rank: continue ratio = (ref_rank - student_rank) / student_rank if ratio < -0.15: tag = "冲" elif ratio < 0.15: tag = "稳" else: tag = "保" recommendations.append((tag, ratio, plan)) recommendations.sort(key=lambda item: item[1]) return recommendations

这里用 aggregate(Max("min_rank")) 取近三年最低位次中数值最大的那个,代表这三年里门槛相对最低的一届,让考生知道自己最低可能落到什么位置。ratio 用于排序,值越小代表往年门槛越高,排在最前面的就是冲刺项,越往后越是保底。代码的优点是逻辑直观、适合答辩展示;缺点是几万条计划时逐条循环会偏慢。毕业设计场景下,可以把结果按recommend:{student_id}:{batch}做缓存,数据更新时再主动清掉。

3.5 数据不足时降级处理

新开专业、中外合作办学项目经常只有一年数据,直接用三年的逻辑会漏掉。降级规则可以分两档:近三年只有一年的,直接用这一年的 min_rank,标签改为“新设专业”;近三年完全没有数据的,不出现在推荐列表,但可以单独展示在“最新计划”模块。实现时在循环里统计 lines.count(),小于 2 时给 plan 加一个提示字段,前端显示成灰色标记,避免用户误判。

4. 从压缩包到浏览器:环境配置、数据库连接与 Django 后台使用

项目能不能跑起来,八成问题出在环境而不是代码本身。这套代码在 macOS 和 Windows 10/11 上都验证过,但每台机器的 Python 环境差异,还是会遇到各种各样的报错。这一章按顺序操作,基本能打开前台和管理端。

4.1 解压后的项目里都有什么

解压后通常包含工程配置目录、业务 app、manage.py、requirements.txt、数据库备份目录和文档。大致布局如下:

project/ manage.py requirements.txt zhiyuan/ # 工程配置目录 settings.py urls.py wsgi.py core/ # 业务 app,实际名称以压缩包为准 models.py views.py admin.py templates/ # 页面模板 static/ # css/js/图片 database/ # 数据库备份或初始数据 docs/ # 设计文档、说明

先打开 requirements.txt 看依赖清单,再创建虚拟环境安装。不要直接往系统 Python 里塞依赖,容易和机器上别的项目相互干扰。

4.2 本地环境准备与依赖安装

python -m venv venv source venv/bin/activate venv\Scripts\activate # Windows 下执行这条 pip install -r requirements.txt

第一条命令创建虚拟环境,后两条分别是 macOS/Linux 和 Windows 下的激活方式。requirements.txt 里通常会包含 Django、MySQL 驱动、pandas 这些依赖。安装完成后用python -c "import django; print(django.get_version())"确认 Django 能正常导入。

4.3 settings 里连接数据库

项目可能默认使用 SQLite,也可能要求连 MySQL,具体看压缩包附带的说明文档。Django 的数据库配置集中在 settings.py 里,改动点如下:

DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", "NAME": "volunteer_db", "USER": "root", "PASSWORD": "你的数据库密码", "HOST": "127.0.0.1", "PORT": "3306", "OPTIONS": {"charset": "utf8mb4"}, } }

ENGINE 指定数据库后端,NAME 是库名,需要先在 MySQL 里建好库。OPTIONS 里的 utf8mb4 很重要,高校专业名称里各种特殊字符都能存。如果只是想本地先把项目跑起来,把 ENGINE 换成django.db.backends.sqlite3,NAME 改成db.sqlite3就行,不用装 MySQL。

4.4 迁移、初始数据和管理员账号

数据库连接改好后,按顺序执行:

python manage.py makemigrations python manage.py migrate python manage.py createsuperuser python manage.py runserver

迁移会把 models.py 定义的表结构写进数据库。createsuperuser 按提示输入用户名、邮箱、密码,这个账号用来登录 /admin/。runserver 默认监听 8000 端口,浏览器访问 http://127.0.0.1:8000/ 打开前台,访问 /admin/ 打开管理后台。如果 8000 被占用,指定新端口:python manage.py runserver 8080

4.5 把核心模型注册进 admin

压缩包里的后台通常已经注册好了模型,如果要自己把新表加进去,admin.py 可以这样写:

from django.contrib import admin from .models import School, RecruitPlan, ScoreLine @admin.register(School) class SchoolAdmin(admin.ModelAdmin): list_display = ["code", "name", "province", "level"] search_fields = ["code", "name"] @admin.register(RecruitPlan) class PlanAdmin(admin.ModelAdmin): list_filter = ["year", "batch"] search_fields = ["school__name", "major__name"]

list_display 决定列表页显示哪些列,search_fields 生成搜索框,list_filter 在页面右侧生成过滤器。外键字段在 search_fields 里用双下划线写法,比如 school__name,这样就能按学校名称直接搜索招生计划。

4.6 运行阶段常见错误与排查

报错信息可能原因处理方式
No module named 'MySQLdb'缺少 MySQL 驱动pip install mysqlclient,或确认 requirements 已包含
Unknown column ... in 'field list'数据库旧表与 models 不一致备份数据后重新 migrate 对应 app
DisallowedHost 报错ALLOWED_HOSTS 限制开发期在 settings.py 里加入 127.0.0.1
静态文件 404DEBUG=True 配置或静态目录未识别检查 STATICFILES_DIRS 指向的路径

以上四条是接手 Django 毕设项目最常见的启动问题。出现 DisallowedHost 时,把 ALLOWED_HOSTS 临时设置成["*"]可以快速定位是不是域名配置问题,但别长期留在生产环境。静态文件问题绝大多数是路径没对齐,检查 static 目录是否在项目根路径下。

5. 把 Excel 招生计划批量灌进系统:一个能直接改的导入脚本与三个坑

招生计划每年更新一次,数量大、格式每年都略有变化。后台逐条录几百所院校的计划,录入慢还容易错,批量导入脚本是实际使用中最该先做的一步。

5.1 为什么需要独立导入脚本

Django admin 适合维护单条数据,不适合大批量初始化。Excel 里的列基本能对应上 RecruitPlan,但学校名和代码要关联到 School 表,专业名要关联到 Major 表,先查再插或先插再查的逻辑需要脚本统一处理,并且要允许重复执行不产生重复数据。

5.2 用 pandas 读取并逐行写入数据库

import pandas as pd from your_app.models import School, Major, RecruitPlan df = pd.read_excel("plan_2024.xlsx", dtype={"院校代码": str, "专业代码": str}) errors = [] for idx, row in df.iterrows(): school, _ = School.objects.get_or_create( code=row["院校代码"], defaults={"name": row["院校名称"]}) major, _ = Major.objects.get_or_create( code=row["专业代码"], defaults={"name": row["专业名称"]}) try: RecruitPlan.objects.update_or_create( school=school, major=major, year=int(row["年份"]), batch=row["批次"], defaults={"plan_num": int(row["计划人数"]), "subject_req": str(row["选科要求"])}) except Exception as exc: errors.append((idx, str(exc))) print("完成,失败行数:", len(errors))

get_or_create 先按院校代码查,查不到再新增,返回的 created 标志可以判断是插入还是复用。update_or_create 按学校、专业、年份、批次四个字段做唯一性判断,同一个计划不会重复插入,只会更新计划数和选科要求。每行的异常收集到 errors 列表而不是直接中断,跑完一眼就能看到哪些行需要人工修正。

5.3 在 Django shell 里执行导入

脚本不能直接python import_plan.py,因为模型依赖 Django 的 settings 信息。常见做法有两种:

python manage.py shell -c "exec(open('import_plan.py', encoding='utf-8').read())"

也可以进入 shell 后手动粘贴代码。第一次跑之前先执行df.head()确认列名,不要拿着真实数据直接跑,导入工具一旦匹配错列,后续清理要花更多时间。

5.4 Excel 表格里的三个典型坑

第一,年份列在 pandas 里可能被读成浮点数,变成 2024.0,写入 IntegerField 前要显式转 int。第二,专业代码前有零容易被吃掉,读 Excel 时必须指定 dtype 为 str,否则字符串“081201”会变成数字 81201。第三,选科要求列可能有很多空值,直接 str(row["选科要求"]) 会把 NaN 变成字符串“nan”,写入前用if pd.isna(row["选科要求"]): subject_req = ""处理。

5.5 导入后的复核查询

导入完成后用聚合查询验证总数和学校数量:

python manage.py shell -c " from your_app.models import RecruitPlan from django.db.models import Count print(RecruitPlan.objects.filter(year=2024).count()) print(RecruitPlan.objects.values('school__name').annotate(num=Count('id')).count())"

第一条输出 2024 年招生计划总数,第二条输出涉及学校数量。如果数量和 Excel 行数对不上,优先检查批次名称里是否有多余空格。shell -c 外面用双引号,内部代码避免再使用和 bash 冲突的引号,这是在 macOS 和 Windows 下都能跑的写法。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 16:10:49

cnsenti轻量中文情感分析:词典规则实现毫秒级极性打分

简介&#xff1a;本资源是基于大连理工大学情感词汇本体库构建的中文情感分析工具包&#xff0c;面向自然语言处理初学者、科研人员及需要快速实现文本情绪识别的开发者。它支持正负情感倾向判断与细粒度情绪分类&#xff0c;适用于舆情分析、用户评论挖掘、教育反馈评估等典型…

作者头像 李华
网站建设 2026/9/16 16:10:43

NFT数字藏品交易平台搭建:从链上确权到订单撮合的完整实现

简介&#xff1a;一套可运营的元宇宙数字藏品艺术品交易平台完整源码&#xff0c;旨在帮助站长、创业者及PHP开发者快速搭建数字藏品发布与交易网站&#xff1b;平台前端采用Vue框架&#xff0c;后端基于ThinkPHP&#xff0c;覆盖藏品展示、发布、下单交易等常用流程。部署环境…

作者头像 李华
网站建设 2026/9/16 16:09:47

深入解析.NET运行时加载中的wks与svr模式差异

1. 深入解析CorBindToRuntimeEx中的"wks"参数作为一名长期从事.NET与COM互操作开发的工程师&#xff0c;我经常需要处理各种运行时加载问题。今天要讨论的这个"wks"参数&#xff0c;看起来简单却暗藏玄机。记得我刚接触这个参数时&#xff0c;曾因为忽略它…

作者头像 李华
网站建设 2026/9/16 16:09:25

基于Django的宿舍管理系统:ORM设计、核心业务与部署实战

简介&#xff1a;面向高校课程设计与期末大作业场景&#xff0c;这份Python Django学生宿舍管理系统提供了可直接运行的完整工程&#xff0c;包含后端业务逻辑、前端页面与数据库脚本&#xff0c;适合正在学习Web框架开发或需要快速交付项目的同学参考。项目已通过导师指导并获…

作者头像 李华