简介:一套完整的Python医院信息系统课程设计源码包,主要面向计算机相关专业学生,尤其适合正在完成小组作业或课设项目的开发者参考。项目围绕患者管理、医生排班、药品库存、财务结算等HIS核心业务场景,综合运用Python后端、Vue前端与SQL数据库脚本,贯穿需求分析、数据库设计、接口开发、前后端联调与部署维护全流程,有助于快速掌握医疗信息系统的业务逻辑与Python Web开发实战方法。资源共67个文件,压缩包仅497KB,其中包含14个Python源码文件、21个Vue组件/页面文件、8个JavaScript逻辑文件、4个SQL初始化脚本,并辅以配置文件和说明文档,目录按server、client划分,结构清晰。已有428人学习下载,既可作为课程设计或毕业设计的功能蓝本,也能从中学习RESTful API设计、ORM操作、Vue组件化开发等技能,适合前后端分离项目的协作开发参考。
1. 先别急着装依赖:这份 Python 医院信息系统到底给了你什么
如果你正在找一个能跑通演示、写得出实验报告、答辩时讲得清架构的 Python 课设,这份《Python医院信息系统.zip》是典型的前后端分离结构。解压后 his-master 目录里同时躺着 Django 后端(server 和 manage.py)、两个前端工程(client 与 manage 各自的 src 和 package.json)、以及 test_data 下的三张核心表 SQL 脚本——科室、用户、通知。它解决的是小组作业最现实的三个问题:代码能不能跑、模块怎么划分、数据从哪来。适合正在做信息系统分析与设计课设、需要交付完整工程而不是 PPT 的同学,也适合想拆解最小 HIS 权限模型的开发者。
2. 项目结构与权限设计:从 his-master 目录看前后端分工
2.1 三个目录,三种职责:先看懂谁在干活
解压后第一件事不是急着装依赖,而是把目录结构读一遍。his-master 根目录下 README.md 是项目说明,剩下三块:server、client、manage。server 是 Django 后端工程,里面有 manage.py、app 业务包和 server 配置包;client 和 manage 都是带 package.json 的前端工程。第一眼看到两个前端目录可能会愣住,但在课程设计里这很常见——client 做业务前台,manage 做管理后台,两个应用共用同一个 Django 后端,登录后按角色跳转。
| 目录 | 类型 | 职责 |
|---|---|---|
| server | Django 后端 | 提供 API、处理登录鉴权、对接数据库 |
| client | 前端工程 | 业务前台,面向医生和患者 |
| manage | 前端工程 | 管理后台,面向系统管理员 |
| test_data | 数据脚本 | 存放 departments.sql、users.sql、notices.sql |
为什么这么拆?答辩时老师几乎必问“你的系统有哪些角色”,双前端加角色字段的方案能直接回答这个问题:医生和患者在 client 端操作,管理员进 manage 端管基础数据。实际开发时两个前端各自 npm install、各自启动,端口不同,通过代理指向同一个 8000 后端。如果两个前端都往同一个后端打请求,后端只需要一套接口,不用各写一遍。
2.2 后端 app 划分:业务模块怎么拆才经得起追问
server/app 是后端业务核心,课程设计包里最常见的做法是单 app 多 Model,而不是像生产项目那样拆成 registration、outpatient、pharmacy 一堆子应用。单 app 的好处是迁移文件集中、依赖关系一眼看完,对小组作业来说写起来快,提交代码时也不会因为目录太深讲不清。但答辩时不要只说“一个 app”,要把 Model 按业务域讲清楚。
挂在 app 下的 Model 通常覆盖:科室、用户、挂号记录、就诊记录、药品库存、费用结算。这些正好对应摘要里说的挂号模块、就诊模块、药房模块、财务管理。如果后端代码里已经分了多个业务文件,那就按文件讲;如果全堆在 models.py 里,我一般会按“基础数据—业务数据—财务数据”三层来组织讲解:科室、用户是基础数据;挂号、就诊是业务数据;费用是财务数据,三层之间通过外键串联。
这里有个容易被追问的点:为什么用户表和科室表要有外键关系。答案要落到“一个医生必然属于某个科室,排班和挂号都依赖这个归属关系”。在 models.py 里通常用 ForeignKey 实现,后面第三章会讲具体写法。先把模块边界讲清楚,后面答辩时节奏就稳,不至于被问到“你这个模块边界在哪”时支支吾吾。
2.3 三张核心表:科室、用户、通知的数据边界
test_data 下三张 SQL 是整套系统的地基:departments.sql 定义科室,users.sql 定义用户和角色,notices.sql 定义通知公告。三张表的关系是:用户通过外键归属到科室,通知不依赖科室独立存在。
departments 表通常有三个字段:id 主键、name 科室名、location 就诊位置。users 表是账号体系,至少包含用户名、密码哈希、角色字段,角色值一般就是 admin、doctor、patient 三个。notices 表更简单,标题、正文、发布时间就够了,它的作用是让系统“有东西可以展示”,演示时直接把公告列表挂在首页,比空荡荡的页面有说服力。
为什么把这三张表单独拿出来做成 SQL 而不全交给 Django migrate?这是课程设计里很实际的做法:migrate 负责建 Django 自己的表(session、auth 等),业务基础数据用 SQL 脚本导入,保证所有人拿到的科室列表、测试账号完全一致。演示前只需要执行一次导入,不需要手工在后台点鼠标录入。别小看 test_data 这个目录,它是演示前的后悔药——凡是手工在后台点的数据,换台电脑全没;SQL 一导就回来了。这个数据边界划分好了,后面所有联调都省事。
3. Django 后端:从 manage.py 到接口响应的完整链路
3.1 虚拟环境和 manage.py 常用命令
先搭环境。server 目录下按惯例会有一份 requirements.txt,解压后第一件事是确认它在不在;如果不在,就按最小依赖装:django、djangorestframework、django-cors-headers。以下是我一般会走的流程:
cd his-master/server python -m venv venv source venv/bin/activate # Windows 下用 venv\Scripts\activate pip install -r requirements.txt python manage.py makemigrations python manage.py migrate python manage.py runserver 0.0.0.0:8000第一行python -m venv venv创建虚拟环境,这一步能把依赖隔离在项目内,避免和机器上其他 Python 项目互相污染。source venv/bin/activate是激活虚拟环境,Windows 上路径变成venv\Scripts\activate,这个区别经常让新手卡住。makemigrations把当前 Model 变化生成迁移文件,migrate才真正写库。runserver后面的0.0.0.0是允许局域网访问,方便小组里其他人用http://你的IP:8000联调。
makemigrations和migrate的顺序不能反,这是 Django 新手最容易翻车的地方。makemigrations只是生成文件不碰数据库,migrate才执行建表和字段变更。如果直接跑migrate提示没有变更,多半是上一句没跑,或者 Model 压根没注册进 INSTALLED_APPS。
3.2 模型层与 ORM:基础数据表如何在代码里落地
三张核心表在 SQL 里已经定义了,在 Django 里还得用 Model 重新描述一遍,ORM 才能操作它们。以科室和用户为例,课程设计里常见的模型写法长这样:
# Department:科室主表,migrate 后会落到对应业务表 class Department(models.Model): name = models.CharField(max_length=64, unique=True) # 科室名,唯一约束 location = models.CharField(max_length=128, blank=True) # 就诊位置 def __str__(self): return self.name # UserProfile:扩展 Django 内置用户,挂角色和科室外键 class UserProfile(models.Model): ROLE_CHOICES = [ ('admin', '管理员'), ('doctor', '医生'), ('patient', '患者'), ] user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='profile' ) department = models.ForeignKey( Department, null=True, blank=True, on_delete=models.SET_NULL # 科室删除后用户保留,归属置空 ) role = models.CharField(max_length=16, choices=ROLE_CHOICES, default='patient') phone = models.CharField(max_length=11, blank=True)科室名用CharField加unique=True保证不重复,这是业务上的硬约束。UserProfile 通过OneToOneField关联 Django 自带的用户表,这是扩展 Django 用户模型最常见的做法:不动 auth_user 表结构,只加一张 Profile 表存角色、科室、电话。department外键是关键,on_delete=models.SET_NULL表示科室被删的时候用户记录保留,只是归属变空;如果业务上不允许无科室医生,可以改成PROTECT。角色用choices限定三个固定值,比自由填字符串更稳。
注意一个细节:这里的表名和 test_data 里的 SQL 表怎么对应。如果 SQL 里表名是his_department、his_user_profile,要在 Model 的 Meta 类里用db_table指回去,否则 migrate 会另建一张新表,导致你导入的科室数据“没了”。这个坑我放在第五章展开讲,这里先记住:SQL 里的表名和 Model 的类名不一定一致,对应不上就是数据“消失”的根源。
3.3 视图、序列化与路由:一个接口的完整拆解
后端接口部分,课程设计包最常见的是用 Django REST Framework 的 ViewSet,而不是每个接口手写函数视图。理由是业务接口基本都是 CRUD,ViewSet 一行声明就带出增删改查,DefaultRouter 自动生成路由,节省时间且答辩好讲。
# serializers.py:负责模型和 JSON 之间的转换 from rest_framework import serializers from .models import Department class DepartmentSerializer(serializers.ModelSerializer): class Meta: model = Department fields = ['id', 'name', 'location'] # 只暴露这三个字段 # views.py:ViewSet 自动提供 list/create/update/delete from rest_framework import viewsets from .models import Department from .serializers import DepartmentSerializer class DepartmentViewSet(viewsets.ModelViewSet): queryset = Department.objects.all() serializer_class = DepartmentSerializer序列化器里fields显式列出要暴露的字段,前端拿不到多余字段,这是安全和整洁的关键。ViewSet 里只要定义queryset和serializer_class,增删改查接口就齐了。路由注册放在 app 的 urls.py 里:
# app/urls.py from rest_framework.routers import DefaultRouter from .views import DepartmentViewSet router = DefaultRouter() router.register('departments', DepartmentViewSet, basename='department') urlpatterns = router.urlsDefaultRouter会为 ViewSet 生成/departments/的列表接口和/departments/{id}/的详情接口。如果前端请求路径是/api/departments/,那在根 urls.py 里加一层前缀:path('api/', include('app.urls'))。调接口时注意细节:前端一定要请求/api/departments/这种带末尾斜杠的地址;手写路径时漏掉结尾斜杠,Django 会返回 301 让你重定向,跨域情况下重定向经常直接被浏览器拦截,表现成“接口变红”,排查时先看网络面板里是 301 还是 200。
4. 前端联调:client 与 manage 的目录分工和数据流
4.1 两个前端工程:分别服务谁
client 和 manage 都是前端工程,目录结构相近,职责不同。client 是业务前台,医生录病历、患者挂号都在这里;manage 是管理后台,维护科室字典、发布通知、查看统计数据。用表格看更清楚:
| 前端目录 | 典型内容 | 服务对象 |
|---|---|---|
| client/src/views | 挂号页、病历页、药品页 | 医生、患者 |
| manage/src/views | 科室管理、用户管理、公告管理 | 管理员 |
| src/api | axios 请求封装 | 前端通用 |
| public | 静态资源、index.html | 打包时原样复制 |
有些课程设计会把两个前端合并成一个,用路由区分 /admin 和 /client,但这份资源把二者拆成两个独立工程,好处是权限边界在物理上就分开了:管理后台的代码根本不在业务前台的包体积里,答辩时讲权限控制有真实依据。缺点是npm install要跑两遍、开发时要起两个 dev server。我一般先起后端,再起 client,最后起 manage,三个终端窗口对应三个进程,谁挂了一目了然。
4.2 代理转发与请求封装:前端如何拿到后端数据
前端和后端端口不同(前端常见 8080 或 5173,后端 8000),直接 fetch 会产生跨域请求。排查课设联调问题时,十次里有八次是跨域配置漏了。常见做法是在前端工程根目录加 vue.config.js 配置开发代理,路径带 /api 的请求全部转发到 Django 后端:
// vue.config.js module.exports = { devServer: { port: 8080, proxy: { '/api': { // 所有带 /api 前缀的请求 target: 'http://127.0.0.1:8000', // 转发到 Django changeOrigin: true } } } }再配一个 axios 实例,把 baseURL 固定成 /api,这样所有请求天然走代理,后端也统一挂在 /api 前缀下:
// src/api/request.js import axios from 'axios' const request = axios.create({ baseURL: '/api', // 统一前缀,走 devServer 代理 timeout: 10000 }) export default requestchangeOrigin的作用是让后端看到的 Host 变成 target 的地址,避免 Django 因 ALLOWED_HOSTS 校验拒绝请求。如果后端只允许本机访问,把 target 写成 127.0.0.1 而不是 localhost,有些机器上两者解析到不同地址。这些配置看着简单,漏一个就是联调半天找不到原因。
4.3 角色路由守卫:管理员、医生、患者各看各的
两个前端工程各自的路由守卫逻辑基本一致:登录成功后把 token 和角色写进 localStorage,路由跳转前读角色判断放不放行。下面是一段常见的 Vue 2 路由守卫写法:
// src/router/index.js import Vue from 'vue' import Router from 'vue-router' import routes from './routes' Vue.use(Router) const router = new Router({ routes }) // 全局前置守卫:每次跳转前先做权限校验 router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') const role = localStorage.getItem('role') if (to.meta.requiresAdmin && role !== 'admin') { next('/403') // 非管理员访问管理页,先隔离 return } if (to.meta.requiresAuth && !token) { next('/login') // 未登录跳登录页 return } next() }) export default router逻辑不复杂,但要确保登录接口返回的数据里同时有 token 和 role,且名称和前端读取的完全一致。课设里常见的翻车点是后端返回的是user_info.role,前端读的是role,永远读不到,于是登录成功后一直跳回登录页。排查这类问题,打开浏览器控制台 Application 面板看 localStorage 里到底写入了什么,比盲目改代码快得多。如果这份资源里 token 是放在请求头 Authorization 的,后端视图里取的时候也要对得上,否则就会出现“接口 401、登录却成功”的割裂现象。
5. 从解压到跑通:环境搭建、数据初始化与常见问题排查
5.1 解压、虚拟环境与依赖安装:先把三件套立起来
拿到 zip 包第一件事是解压,Windows 右键“全部解压缩”,Linux 上用一行命令:
unzip Python医院信息系统.zip -d his # -d 指定解压到 his 目录 cd his/his-master python -m venv venv # 创建虚拟环境 source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt # 装依赖unzip -d his指定解压目标目录,防止压缩包把所有文件散在当前目录。再把 server 目录下的 requirements.txt 装好。如果没找到这个文件,退一步按最小依赖装 django、djangorestframework、django-cors-headers,这三个包就能撑起后端主体功能。pip install慢的时候就换国内镜像源,在命令里加-i参数指向镜像地址即可,不用改全局配置。装完依赖跑一遍python manage.py check,它会告诉你 settings 里有没有明显错误,这是进数据库之前的快速体检。
5.2 数据库准备:先导 SQL 还是先 migrate,顺序定了不返工
先给结论:先建库、再导三张业务 SQL、最后执行 migrate。这样 Django 自带的表在业务表旁边一并补齐,且不会覆盖已导入的数据。
mysql -u root -p -e "CREATE DATABASE his DEFAULT CHARACTER SET utf8mb4;" mysql -u root -p his < test_data/departments.sql mysql -u root -p his < test_data/users.sql mysql -u root -p his < test_data/notices.sql python manage.py migrate python manage.py createsuperuser第一条命令建库,utf8mb4一定要写,否则中文科室名、通知标题都可能变问号,这是导入后最常被看到的现象。三条 SQL 导入顺序不能乱:users.sql 依赖 departments.sql 的科室 id,先导科室再导用户。migrate放到最后,是因为 Django 的 migrate 只会创建 auth 等框架表和 Model 里没有对应 SQL 的新表,不会去动已经存在的业务表。createsuperuser创建的管理员账号,登录 manage 后台和 Django admin 都用它。
如果先跑了 migrate 再导 SQL,而且 Model 里又没配置db_table,就会出现两张同名表:一张是 migrate 建的,一张是 SQL 导入的,数据跑到另一边去了。判断方法是进入数据库执行SHOW TABLES,看到his_department和app_department同时存在,基本就是没对上。解决办法是删掉空白的那张业务表,或者在 Model 的 Meta 里把db_table指到 SQL 建的表名。
注意:登录接口校验的是 Django auth_user 表的密码哈希。如果 users.sql 只导入了业务用户扩展表而没给 auth_user 写入记录,SQL 里的测试账号是登录不了的,先使用
createsuperuser创建管理员账号做联调。
5.3 常见问题排查:联调阶段最容易翻车的五个点
课程设计联调阶段,大部分问题集中在下面五处。每条按现象、原因、解决来梳理,都是实际会遇到的组合。
现象:前端页面能打开,接口请求全红。
原因:跨域没配,或者 Django 的 ALLOWED_HOSTS 没加前端地址。解决:先在浏览器 Network 面板看响应头有没有Access-Control-Allow-Origin。没有说明 CORS 中间件没生效,回到 INSTALLED_APPS 确认 django-cors-headers 在列、corsheaders.middleware.CorsMiddleware在 MIDDLEWARE 里且位置优先;同时把 ALLOWED_HOSTS 设为['*']或写入局域网 IP。
现象:SQL 导入后中文全部乱码,登录页都是问号。
原因:建库时没指定 utf8mb4,或者 SQL 文件本身是 GBK 编码而客户端按 UTF-8 导入。解决:重建数据库并显式指定字符集,导入前在 mysql 客户端先执行SET NAMES utf8mb4。如果 SQL 文件是从 Windows 导出的,用文本编辑器另存为 UTF-8 编码再导入。
现象:python manage.py migrate 报“No changes detected”。
原因:这个 app 不在 INSTALLED_APPS 里,或者 Model 写在建库脚本里而应用内没有对应模型。解决:确认 settings 的 INSTALLED_APPS 包含 app 名;执行python manage.py makemigrations app强制应用内扫描一遍,再看生成的迁移文件内容。
现象:登录接口返回成功,但页面立刻跳回登录页。
原因:前端 localStorage 存的 key 和后端返回字段对不上,或者路由守卫判断逻辑写死。解决:在控制台打印 localStorage 内容,核对 token、role 两个键是否存在。如果后端返回的是嵌套结构如data.token,前端要取data.token而不是整段响应。
现象:npm install 到一半报错,或者启动时提示版本不兼容。
原因:Node 版本和前端工程的依赖要求不匹配,常见于 Vue 2 工程跑在新版 Node 上。解决:用 nvm 切到工程兼容的 Node 版本,课程设计环境一般切到 16 或 18 就能过;不要手动改 node_modules,多半越改越乱。
这五条覆盖了从解压到演示最常见的翻车点。每一条都是“先看日志再动手”:浏览器 Network、控制台、Django runserver 的终端输出,三个地方轮流看,比瞎改配置快得多。runserver 终端里会打印每条请求和状态码,如果接口 500,Django 的报错堆栈会直接打在终端里,那是最可靠的排错入口,别绕过它去猜。
6. 验证与答辩:按角色走完整流程,把“能跑”变成“能讲”
系统跑起来只是第一步,演示和答辩才决定课程设计的得分。核心方法是把用户故事当测试用例:用 createsuperuser 建的账号登录 manage 后台,创建一个“内科”科室,再发布一条通知;然后用 users.sql 里预置的测试账号登录 client 端,完成一次挂号,观察挂号记录是否出现在医生端的待诊列表里。这条链路覆盖了三张核心表、两类角色和至少四个接口,是整份资源的业务主流程。跑通后把 runserver 终端、npm 终端各自截图保存,作为开发过程记录,答辩时直接放在 PPT 的“系统实现”页。
答辩中最容易被追问的是“你的表和接口怎么对应的”。回答脉络是:科室是基础数据,用户挂在科室下,挂号记录关联医生和患者,财务记录由挂号结算产生。这个脉络和数据库外键方向完全一致。演示时万一某个接口 500,不要慌着刷新页面,先看 Django 终端最后一段堆栈,照着错误信息念出“数据库字段或序列化配置的问题”,比假装没看见体面得多。我一般还会在答辩前做一次“冷启动演练”:把两个前端和数据库全部关掉,按第五章的顺序从解压和建库重新走一遍,确保换了机器也能复现。
需要这份源码包的话,直接搜标题关键词就能在下到的压缩包里看到整套工程,解压后先导数据再动代码。讲个习惯:从那以后我每次拿到课设包,第一件事就是把三张 SQL 按顺序导一遍再碰代码;代码可以慢慢看,数据基础先立住,后面所有调试都省时间。希望这份拆解能帮你少走点弯路,把那份 zip 真正变成能讲、能演示、能得分的作品。
本文还有配套的精品资源,点击获取