
简介面向高校信息系统课程小组作业场景的Python医院信息系统完整工程包适合正在学习Web开发、数据库设计或需要快速搭建HIS项目示例的开发者。资源采用前后端分离结构后端以Python为主包含Django/Flask风格的server工程与manage.py入口前端为Vue项目配有多份JavaScript、HTML、CSS及页面组件另有SQL建表脚本、JSON配置和项目说明文档覆盖从数据建模到界面展示的主要环节。压缩包共67个文件约497KB文件类型以vue、py、js、sql、md等为主目录结构清晰便于按模块检索。内容预览可见his-master下包含server、client、src、test_data等模块并附有多张业务数据表的初始化SQL脚本可直接对照学习业务表关系与数据初始化也可作为小组分工开发的起点。已有428人学习下载适合作为课程设计参考、小组协作模板或Python信息管理系统入门实践。1. 医院信息系统小组作业的实战拆解一个zip里藏着完整的HIS开发链路一份Python医院信息系统的小组作业解压以后其实是一整套前后端分离的HIS骨架Django写的REST服务端、node生态的前端工程、三张核心业务表的SQL初始化脚本外加test_data目录里已经放好的测试数据。这套资源对两类人特别值钱一类是正在做课程设计、需要参考完整项目结构的学生另一类是刚接触医疗行业开发、想快速搞清HIS模块和数据库怎么设计的工程师。它不是一个只有空壳的demo而是从数据库表到业务接口再到前端页面都能跑通的完整闭环。2. 技术栈与目录结构从server/到src/先认清这套HIS用什么搭的拿到zip先别急着跑第一步是把目录读明白。这套his-master的布局非常典型server/目录是Django的服务端代码里面套着app/和server/两层外层有departments.sql、notices.sql、users.sql三个SQL文件根目录还有public/、src/、package.json、package-lock.json——这是前端工程的标配。public是静态入口src是源码目录package-lock.json说明依赖已经锁定过版本。一眼扫过去前后端分离的工程结构就清楚了。2.1 Django后端与REST架构manage.py背后的模块划分逻辑server/manage.py是Django的标准启动入口。manage.py所在的server/目录下与manage.py同级的server/子目录存放settings.py、urls.py、asgi.py这些核心配置app/目录才是业务模块代码。在Django工程里app/和server/目录并存是正常现象前者是业务应用后者是项目配置。这套布局就是Django官方推荐的“单项目多应用”结构。课程设计通常把挂号、患者、公告这些功能集中在一个app里实现不拆多个app——拆多了反而显得代码碎片化。选型上为什么是Django而不是Flask来写医院信息系统我的判断是HIS虽然对外是一个Web系统但它骨子里是对数据模型要求极高的管理信息系统。Django自带ORM、Admin后台、迁移机制、用户认证这些能力正好覆盖了HIS最耗时间的部分。你用Flask写光是把用户认证和数据迁移这两块搭起来就要多花好几天而Django这些能力开箱就有。client/和test_data/放在server/下也值得讲一句这两块本该在服务端之外独立存在但小组提交时为了方便经常塞在一起。这也是我判断一套代码是否“实操过”的依据之一——目录整洁度往往比代码本身更能暴露项目真实状态。# 查看Django版本与迁移状态 cd server python manage.py --version python manage.py showmigrationsshowmigrations的输出里可以看到哪些迁移已经应用、哪些还没有。拿到一套新项目这一步比直接runserver更稳妥——它能在启动前就暴露数据库缺失、迁移文件损坏这类问题。2.2 前端工程与构建链路package.json和src目录对应的界面层前端部分用的是标准Node.js生态。package.json里的scripts字段定义dev和build命令src/下面是组件和页面源码public/放静态资源。课程设计里前端大多用Vue或React的脚手架起项目所以最终目录里会出现package-lock.json——这是npm install之后自动生成的依赖锁文件它的存在说明本地已经跑过依赖安装比只有package.json可信得多。拿到package.json先看三样scripts里的启动命令、dependencies里的框架版本、devDependencies里的构建工具。我一般不会先读README而是直接npm install再npm run dev看它监听哪个端口。这样比读文档更快也更容易发现文档和代码不一致的地方——比如README说前端跑在8080实际上dev脚本里写的端口是5173。# 前端依赖安装与开发服务器启动 cd his-master npm install npm run devnpm install会按照package-lock.json里的固定版本安装依赖这一步如果出现ERR!的报错优先检查Node版本是否满足package.json里engines字段的要求。npm run dev启动开发服务器后控制台会输出一个本地访问地址记住这个端口后面联调要用。前端页面里与后端交互的部分通常集中在src/api/目录或某个request工具模块中。它通过axios之类的库发起HTTP请求指向Django后端地址。由于后端Django默认跑在8000端口前端开发服务器通常在5173或3000端口两者之间需要配置代理或者后端开启CORS否则浏览器跨域会直接拦截——后面避坑章节会专门展开。2.3 SQL初始化脚本departments、notices、users三张核心表的职责三个SQL文件是理解这套系统业务最快的入口。它们的命名方式一看就是分别对应用户中心、科室组织、公告通知三个模块。departments.sql是科室表它就是整个医院系统的组织架构锚点。医院里的所有业务——挂号、排班、公告、医嘱——都围绕科室挂接。notices.sql是通知公告表结构里大概率有department_id外键说明通知是科室维度的users.sql是用户表支撑登录认证。三张表的关联关系就是这套HIS的最小业务闭环用户登录后看到自己所属科室再按科室范围操作系统功能、查看通知。从导入顺序上讲应该先导departments再导users和notices因为后面两张表的外键依赖departments的主键。如果你连外键关系都没看就往MySQL里导撞上“Cannot add foreign key constraint”是必然的。这也是一个判断点一套SQL脚本的导入顺序是否在README里写清楚直接决定了别人第一次跑通的概率。数据规模上课程设计级别的SQL脚本一般会预置几十条科室数据、几十个用户、若干条通知足够演示页面效果但不会把真实的医院字典数据塞进来。如果你要拿它做二次开发重点看的是表结构设计思路而不是去扩充种子数据量。SQL里还有一个容易被忽略的细节users表的密码字段如果是明文那这个项目大概率只是演示水平如果是类似pbkdf2_sha256$这样的Django密码哈希前缀说明开发者用Django自带的make_password生成过登录逻辑是正经的。3. 核心业务模块实现科室、通知与用户权限的数据链路医院信息系统跟普通CRUD项目最大的差别在于数据模型强依赖“组织架构”这个维度。科室是顶级组织单元用户挂靠科室通知按科室发布业务数据挂号记录、排班、病历都落在科室下。看清这套层级关系你就知道app/下的models.py应该怎么组织——几乎所有业务表都会带一个外键指向科室或用户。3.1 自定义用户模型与角色权限不只在表里加一个role字段users表是这套系统的认证核心。一般会包含username、password_hash、role、department_id、email、phone这些字段。role字段用来区分管理员、医生、护士实现不同角色看到不同菜单、调用不同接口的权限控制。password字段存哈希而不是明文这是Django里最基本的规范——小组作业也不该裸存密码。Django自带User模型和认证系统但很多HIS项目会选择自定义用户模型。原因很直接需要在用户表里加department_id外键关联科室还要加role、employee_no这类业务字段。自定义User模型有个前置坑必须在第一次migrate之前设置好AUTH_USER_MODEL否则后续改模型设计会变得很难清理甚至需要重建数据库。# settings.py 中注册自定义用户模型 AUTH_USER_MODEL app.User # app/models.py 中扩展用户字段 from django.contrib.auth.models import AbstractUser from django.db import models class User(AbstractUser): ROLE_CHOICES ( (admin, 管理员), (doctor, 医生), (nurse, 护士), ) role models.CharField(max_length16, choicesROLE_CHOICES, defaultdoctor) department models.ForeignKey( Department, nullTrue, blankTrue, on_deletemodels.SET_NULL, verbose_name所属科室 ) employee_no models.CharField(max_length32, blankTrue, verbose_name工号)三个字段的意义role控制角色department挂接组织架构employee_no对应医院工号体系。实际使用中登录后通过request.user.role判断前端显示哪些菜单通过request.user.department_id过滤业务数据。这里要特别提醒AbstractUser继承了Django原生的is_staff、is_superuser字段如果你已经习惯用is_staff做权限判断建议把角色逻辑统一塞到role字段里两套体系并存容易在后期出现越权漏洞——某个视图用了request.user.is_staff判断另一个用了request.user.role管理员角色一多就乱套。3.2 科室树与通知外键数据模型怎么支撑“同科室可见”departments表是组织架构的锚点。它至少需要id、name、code、parent_id字段其中parent_id支持科室的层级结构——内科下面还分心内科、呼吸内科。真实的三级医院科室层级至少有四五层课程设计做到两层也够。notices表在业务上是科室维度的。它的外键指向departments表的科室ID发布时把通知绑定到科室查询时按登录用户的科室过滤。这是实现“同科室医生登录后看到本部门公告”的最简单方案。用Django ORM表示# app/models.py 科室与通知模型 class Department(models.Model): name models.CharField(max_length64, verbose_name科室名称) code models.CharField(max_length32, uniqueTrue, verbose_name科室编码) parent models.ForeignKey( self, nullTrue, blankTrue, on_deletemodels.CASCADE, verbose_name上级科室 ) class Notice(models.Model): title models.CharField(max_length128, verbose_name标题) content models.TextField(verbose_name内容) department models.ForeignKey( Department, on_deletemodels.CASCADE, verbose_name发布科室 ) created_at models.DateTimeField(auto_now_addTrue, verbose_name发布时间)Department用自关联外键parent实现树形结构Notice的department外键指向Department。查询“当前用户所在科室的通知”时先取request.user.department_id再对Notice做filter即可性能开销极小。如果你想按科室层级查询所有子科室通知就需要递归或者引入MPTT方案。本地演示用一层过滤就够了。这里有个设计细节容易忽略关联查询时用select_related预取外键对象可以避免一次请求产生几十条SQL的N1问题。# 加载通知列表并预取科室信息 notices Notice.objects.filter( department_idrequest.user.department_id ).select_related(department)3.3 视图集与序列化器把查询边界收在API层接口层在Django里通常用类视图配合DRFDjango REST Framework来写。一个视图集对应一个模型路由注册后POST、GET、PUT、DELETE就都有了。近似于ModelViewSet。# 以科室通知功能为例的视图层写法 from rest_framework import viewsets from .models import Notice from .serializers import NoticeSerializer class NoticeViewSet(viewsets.ModelViewSet): queryset Notice.objects.all() serializer_class NoticeSerializer def get_queryset(self): user self.request.user if user.role admin: return Notice.objects.all() return Notice.objects.filter(department_iduser.department_id)注意get_queryset的重写逻辑管理员能看全部普通用户只能看到自己科室的通知。对于同时覆盖管理后台与临床用户的HIS系统这几乎是必须的规则。把过滤逻辑收紧在数据源层比在序列化器或前端过滤安全得多——前端可以忽略参数但API层要保证数据根本无法越权获取。序列化器层负责字段格式化与输入校验。这里最常见的坑是read_only_fields漏写比如created_at这种服务端生成的字段在序列化器里没标只读前端表单POST就会一直报缺字段。# serializers.py 注意 read_only_fields 的配置 from rest_framework import serializers from .models import Notice class NoticeSerializer(serializers.ModelSerializer): department_name serializers.CharField( sourcedepartment.name, read_onlyTrue ) class Meta: model Notice fields [id, title, content, department, department_name, created_at] read_only_fields [created_at]加上department_name这个只读字段前端列表页直接显示科室名不用再二次请求科室接口。两行代码省一次HTTP请求在HIS这种列表页密集的系统里收益很明显。4. 本地复现步骤从解压zip到前后端联调跑通的全流程这份资源能不能用关键看你能不能在不看完整文档的情况下把它跑起来。按下面的顺序走比你直接翻README更高效。4.1 环境准备先查版本再装依赖避免一上来就翻车第一步先确认Python与Node版本。Django 3.x或4.x项目通常要求Python 3.8起步前端脚手架大多要求Node 14以上。用命令行确认版本python --version node --version npm --version如果版本不满足优先用pyenv或nvm这样的版本管理工具切换不要直接改系统默认版本——改坏了其他项目连后悔药都没有。然后创建虚拟环境并安装后端依赖cd his-master/server python -m venv venv source venv/bin/activate # Windows 下执行 venv\Scripts\activate pip install -r requirements.txtrequirements.txt是Django项目最常用的依赖清单文件。如果server/下找不到它先到README里找依赖说明再看manage.py同级的目录里有没有Pipfile或pyproject.toml。依赖安装完成后验证Django配置是否正常python manage.py checkcheck命令不连数据库只做配置静态检查能快速发现settings.py里的语法错误和模块引用问题。这一步过了再进数据库环节。4.2 数据库初始化SQL脚本导入顺序与Django迁移的对齐数据库配置通常在settings.py里默认指向MySQL或SQLite。如果项目带departments.sql、notices.sql、users.sql大概率用的是MySQL——只有MySQL场景才需要单独导出SQL脚本SQLite都是靠迁移自动建表的。MySQL初始化流程# 登录MySQL并创建数据库 mysql -u root -p CREATE DATABASE his CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;然后按依赖顺序导入三个SQL文件mysql -u root -p his departments.sql mysql -u root -p his users.sql mysql -u root -p his notices.sql这里的顺序不是随便定的。departments表被users和notices的外键引用必须最先导入否则外键约束检查直接报错。如果你在导入时遇到“Cannot add foreign key constraint”十有八九就是顺序错了或者SQL里混用了utf8mb4与utf8字符集。导入完成后执行Django的迁移检查python manage.py makemigrations --check python manage.py migratemakemigrations --check只检测模型与迁移文件之间有没有差异不生成新文件。如果它输出“No changes detected”说明模型和数据库是一致的如果提示有差异说明项目里可能带了一些未提交的模型改动或SQL脚本和models.py不同步——这种情况要停下来先把差异确认清楚再继续。4.3 启动与联调端口、代理、CORS三件事一次说清后端启动前在settings.py里检查ALLOWED_HOSTS和CORS配置。本地调试时# settings.py 本地调试常用配置 ALLOWED_HOSTS [*] CORS_ALLOWED_ORIGINS [ http://localhost:5173, http://127.0.0.1:5173, ]CORS_ALLOWED_ORIGINS需要放行前端开发服务器的地址如果没装django-cors-headers在前端配置代理也是一样的效果。前后端联调时最常见的失败场景是前端页面能打开但所有接口请求都是红色报错控制台显示“Access to XMLHttpRequest has been blocked by CORS policy”——这就是跨域没放行。启动后端python manage.py runserver 0.0.0.0:8000加上0.0.0.0是允许局域网访问方便同学之间联调。启动前端cd his-master npm run dev看到两个终端都在运行后用浏览器打开前端地址做一次完整登录测试。如果登录接口返回200但页面没跳转优先检查前端请求的baseURL是不是写死成了localhost:8000——这和后面的坑5是同一类问题。5. 避坑记录跑通这套HIS时最常见的五个翻车现场做信息系统类项目数据库和权限两个环节最容易折腾人。以下五个问题我基本每次接手类似资源都会遇到按频率排序你先有数。5.1 坑1SQL导入报“Cannot add foreign key constraint”现象执行mysql导入命令时不是第一个文件报错而是第二个或第三个文件报错表只建了一半。原因导入顺序错误。users和notices表的外键都引用departments表的主键但departments还没导入MySQL外键约束校验直接失败。另一种可能原因是字符集不一致建表语句里utf8mb4和utf8混用。解决按departments、users、notices的顺序导入。如果顺序没问题还是报错就把SQL文件里所有CHARSET统一改成utf8mb4再试。导入成功后可以用SHOW TABLES确认三张表的创建状态。5.2 坑2migrate报“relation already exists”或Duplicate table现象SQL脚本导好了执行python manage.py migrate时报“relation already exists”或者提示表已存在。原因SQL脚本已经建好了表但Django的迁移文件不知道这件事。migrate试图创建同一张表和已有表冲突。解决在导入SQL脚本前先执行migrate让Django先把表建好再用SQL脚本去补充数据。如果已经导入了SQL就得用--fake标记迁移状态让它跳过建表python manage.py migrate --fake app 0001这里的0001是app的第一个迁移编号。--fake的意思是写一条迁移记录到django_migrations表但不执行真正的SQL建表操作。以后再做增量迁移就不会冲突了。5.3 坑3前端能开但接口全垮——CORS跨域没放行现象浏览器打开前端页面静态样式正常但列表接口全部报错。控制台满屏“Access to XMLHttpRequest has been blocked by CORS policy”页面只有壳子没有数据。原因前端开发服务器与后端API端口不同浏览器安全策略拦截了跨域请求。settings.py里没配置CORS白名单或者没装django-cors-headers。解决确认项目是否已引入django-cors-headers没有就先安装然后配置INSTALLED_APPS [ # ... 其他应用 corsheaders, ] MIDDLEWARE [ corsheaders.middleware.CorsMiddleware, # ... 其他中间件 ] CORS_ALLOWED_ORIGINS [ http://localhost:5173, http://127.0.0.1:5173, ]CorsMiddleware要放在中间件列表靠前的位置它的处理顺序会影响所有响应头。如果前端和后端在同一台机器上也可以在前端vite.config.js或vue.config.js里配代理转发路径二选一即可不要两套都配否则排查问题时分不清是哪一层出的错。5.4 坑4pip依赖装不上或装完版本对不上现象pip install时报fatal error或者装完之后Django版本与项目写法不兼容一启动就报import错误。原因requirements.txt里依赖版本没有锁定或下载源不通畅导致安装中断。还有一个很常见的情况项目是2021年写的你2025年安装时pip默认装了最新版Django而Django高版本把很多旧API移除了。解决先确认项目用的Django版本——看manage.py同级的server目录里settings.py顶部注释或者直接在代码里搜import路径。不确定就直接指定一个兼容版本安装pip install Django3.2.25网络不稳时用国内镜像源pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple注意如果requirements.txt里已经用pypi源安装过一半再切镜像源前最好先pip uninstall那几个失败的包避免残留半成品状态。5.5 坑5runserver在跑页面却404或静态资源全丢现象127.0.0.1:8000能打开但访问路径显示404或者前端页面加载时所有CSS、JS文件都是404。原因settings.py里的STATIC_URL和STATICFILES_DIRS没有配置静态文件目录或模板里static标签路径与文件实际位置不一致。解决确认前端构建输出目录的位置在settings.py里加STATIC_URL /static/ STATICFILES_DIRS [ BASE_DIR / client / dist, ]BASE_DIR是Django项目根目录dist是前端构建输出的目录名。如果你不想每次改前端都手动构建那就回到npm run dev的开发模式把API代理配置好前端开发服务器会自己处理静态资源。6. 进阶本机复现后用Gunicorn和Nginx把HIS服务正式跑起来教学演示用runserver没问题但如果要把这套HIS部署到服务器上runserver这种方式就撑不住了。Django官方也明确说明runserver只用于开发调试生产环境必须交给WSGI服务器。先把依赖补齐pip install gunicorn然后用Gunicorn启动cd server gunicorn server.wsgi:application -w 4 -b 0.0.0.0:8000server.wsgi:application指的是server目录下wsgi.py里的application对象-w 4是启动4个工作进程-b指定绑定地址。如果项目里有异步任务或WebSocket需求再换成uvicorn加ASGI模式。前端部分把源码构建成静态文件cd his-master npm run build构建产物会输出到dist或build目录把这个目录交给Nginx托管同时把/api路径反向代理到Gunicornserver { listen 80; server_name your-server-ip; location / { root /path/to/his-master/dist; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }这样前端静态文件由Nginx直接返回所有以/api开头的请求转发给Gunicorn不再依赖CORS——因为前后端在同域下。部署完成后验证方法很直接浏览器访问服务器IP正常打开登录页并完成一次登录、一次科室通知查询接口的数据拉取就说明这套HIS在线上环境是通的。这个阶段最容易被忽略的是Django的ALLOWED_HOSTS换地址后没有改以及DEBUG没有关掉。部署前把DEBUG改为FalseALLOWED_HOSTS写成实际域名或IP不然页面会暴露调试堆栈数据库配置也容易泄露。从那以后我每次拿这类带SQL脚本和Django工程的项目都会先跑一遍makemigrations --check再决定是直接导入SQL还是靠迁移建表部署前也会强制在服务器上完整走一遍登录和数据拉取流程确认不是“本机能跑、上服务器就挂”。一个人工检查点省掉的往往是半夜的修bug时间。希望这些拆解和踩坑记录帮到你少走一步弯路是一步。本文还有配套的精品资源点击获取