1. 项目概述最近用Flask框架开发了一套医院预约挂号系统主要解决传统医院挂号排队时间长、号源管理混乱的问题。这个系统实现了患者在线预约、医生排班管理、管理员数据统计等核心功能已经在本地医院试运行了3个月日均处理预约量超过200人次。系统采用PythonFlask作为技术栈主要基于以下考虑Flask轻量灵活适合快速开发中小型Web应用SQLAlchemy提供的ORM能简化数据库操作Jinja2模板引擎学习成本低与Flask集成度高整体架构简单后期维护成本低2. 系统架构设计2.1 技术选型后端框架Flask 2.0.1优势微内核设计、扩展性强、文档完善关键扩展Flask-WTF表单处理、Flask-Login认证、Flask-SQLAlchemyORM前端技术基础模板Jinja2内置于Flask静态资源Bootstrap 5 jQuery 3.6交互增强AxiosAJAX请求数据库MySQL 8.0生产环境/SQLite开发环境选择依据MySQL适合高并发场景SQLite便于开发测试2.2 三层架构设计表示层Templates ↑↓ 业务逻辑层Flask Views ↑↓ 数据访问层SQLAlchemy Models典型请求流程用户访问URL → 2. Flask路由匹配视图函数 → 3. 视图调用模型查询数据 → 4. 渲染模板返回响应3. 核心功能实现3.1 患者模块3.1.1 预约挂号流程app.route(/make_appointment, methods[GET, POST]) login_required def make_appointment(): if request.method POST: # 获取表单数据 doctor_id request.form.get(doctor_id) time_slot request.form.get(time_slot) # 冲突检测 if Appointment.query.filter_by(doctor_iddoctor_id, time_slottime_slot).first(): flash(该时间段已被预约, error) return redirect(url_for(doctor_list)) # 创建预约 new_appoint Appointment( patient_idcurrent_user.id, doctor_iddoctor_id, time_slotdatetime.strptime(time_slot, %Y-%m-%d %H:%M), statuspending ) db.session.add(new_appoint) db.session.commit() # 生成预约号规则科室首字母日期序号 appoint_no f{new_appoint.doctor.department[:2]}{time_slot[:10].replace(-,)}{new_appoint.id:04d} return render_template(appoint_success.html, appoint_noappoint_no) # GET请求显示医生列表 doctors Doctor.query.all() return render_template(doctor_list.html, doctorsdoctors)关键点使用login_required装饰器确保登录状态时间冲突检测防止重复预约预约号生成规则包含科室和日期信息3.2 医生模块3.2.1 排班批量导入from openpyxl import load_workbook app.route(/upload_schedule, methods[POST]) admin_required def upload_schedule(): if file not in request.files: return 未选择文件, 400 file request.files[file] if not file.filename.endswith(.xlsx): return 仅支持Excel文件, 400 wb load_workbook(file) ws wb.active for row in ws.iter_rows(min_row2, values_onlyTrue): doctor_id, date, time_range row start_time, end_time time_range.split(-) # 按30分钟间隔生成时间段 current datetime.strptime(f{date} {start_time}, %Y-%m-%d %H:%M) end datetime.strptime(f{date} {end_time}, %Y-%m-%d %H:%M) while current end: slot ScheduleSlot( doctor_iddoctor_id, start_timecurrent, end_timecurrent timedelta(minutes30), is_availableTrue ) db.session.add(slot) current timedelta(minutes30) db.session.commit() return 排班表导入成功, 200实现细节使用openpyxl解析Excel文件自动将时间范围拆分为30分钟间隔的时间段事务处理确保数据一致性4. 数据库设计4.1 核心表结构class Patient(UserMixin, db.Model): __tablename__ patients id db.Column(db.Integer, primary_keyTrue) name db.Column(db.String(80), nullableFalse) phone db.Column(db.String(20), uniqueTrue, nullableFalse) id_card db.Column(db.String(18), uniqueTrue) # 身份证号 password_hash db.Column(db.String(128)) appointments db.relationship(Appointment, backrefpatient, lazydynamic) class Doctor(db.Model): __tablename__ doctors id db.Column(db.Integer, primary_keyTrue) name db.Column(db.String(80), nullableFalse) title db.Column(db.String(50)) # 职称 department db.Column(db.String(50), nullableFalse) # 科室 specialty db.Column(db.Text) # 专长描述 schedule_slots db.relationship(ScheduleSlot, backrefdoctor, lazydynamic) class Appointment(db.Model): __tablename__ appointments id db.Column(db.Integer, primary_keyTrue) patient_id db.Column(db.Integer, db.ForeignKey(patients.id)) doctor_id db.Column(db.Integer, db.ForeignKey(doctors.id)) schedule_slot_id db.Column(db.Integer, db.ForeignKey(schedule_slots.id)) create_time db.Column(db.DateTime, defaultdatetime.utcnow) status db.Column(db.String(20), defaultpending) # pending/completed/cancelled symptoms db.Column(db.Text) # 症状描述4.2 索引优化# 在模型定义后添加索引 db.Index(idx_appointment_doctor_time, Appointment.doctor_id, Appointment.schedule_slot_id) db.Index(idx_schedule_doctor_time, ScheduleSlot.doctor_id, ScheduleSlot.start_time)设计考量患者和医生信息分离存储预约记录关联具体时间段为高频查询字段添加复合索引5. 安全防护5.1 认证安全from werkzeug.security import generate_password_hash, check_password_hash class Patient(UserMixin, db.Model): # ... def set_password(self, password): self.password_hash generate_password_hash(password) def check_password(self, password): return check_password_hash(self.password_hash, password)5.2 请求防护from flask_limiter import Limiter from flask_limiter.util import get_remote_address limiter Limiter( app, key_funcget_remote_address, default_limits[200 per day, 50 per hour] ) app.route(/login, methods[POST]) limiter.limit(10 per minute) def login(): # 登录逻辑5.3 敏感数据保护from flask_talisman import Talisman Talisman( app, force_httpsTrue, session_cookie_secureTrue, content_security_policy{ default-src: self, script-src: [self, cdn.jsdelivr.net], style-src: [self, unsafe-inline, cdn.jsdelivr.net] } )6. 部署方案6.1 生产环境部署# 安装依赖 pip install gunicorn # 启动命令 gunicorn -w 4 -b 0.0.0.0:8000 --access-logfile - --error-logfile - app:app6.2 Nginx配置server { listen 80; server_name yourdomain.com; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /static { alias /path/to/your/static/files; expires 30d; } }6.3 数据库备份# 每日备份脚本 mysqldump -u username -p database_name /backups/hospital_$(date %Y%m%d).sql7. 扩展功能7.1 短信通知集成import requests def send_sms(phone, message): url https://sms-api.example.com/send params { phone: phone, text: message, apikey: your_api_key } try: resp requests.get(url, paramsparams) return resp.status_code 200 except Exception as e: app.logger.error(fSMS发送失败: {str(e)}) return False7.2 数据统计报表app.route(/stats/department) admin_required def department_stats(): # 按科室统计预约量 stats db.session.query( Doctor.department, func.count(Appointment.id) ).join(Doctor).filter( Appointment.create_time datetime.now() - timedelta(days30) ).group_by(Doctor.department).all() return render_template(stats_department.html, statsstats)8. 常见问题解决8.1 并发预约冲突问题现象多个用户同时预约同一时间段时可能出现超订解决方案app.route(/make_appointment, methods[POST]) login_required def make_appointment(): try: # 开启事务 db.session.begin() # 使用SELECT FOR UPDATE锁定记录 slot db.session.query(ScheduleSlot).filter_by( idrequest.form.get(slot_id) ).with_for_update().first() if not slot.is_available: db.session.rollback() return 该时段已被预约, 400 # 创建预约记录 appointment Appointment(...) slot.is_available False db.session.add(appointment) db.session.commit() return 预约成功 except Exception as e: db.session.rollback() return 预约失败, 5008.2 性能优化建议数据库连接池配置from sqlalchemy.pool import QueuePool SQLALCHEMY_ENGINE_OPTIONS { poolclass: QueuePool, pool_size: 10, max_overflow: 20, pool_timeout: 30 }缓存热门科室数据from flask_caching import Cache cache Cache(config{CACHE_TYPE: SimpleCache}) app.route(/departments) cache.cached(timeout3600) def list_departments(): return jsonify([d.name for d in Department.query.all()])9. 项目总结这套系统经过三个月的开发和优化目前已经稳定运行。在实现过程中有几个关键经验值得分享时间处理要统一所有时间字段都存储为UTC时间在显示时根据用户时区转换事务管理要严谨涉及多表更新的操作必须放在事务中日志记录要全面关键操作都要记录日志便于问题排查对于想要扩展功能的开发者建议考虑增加在线问诊功能对接医保支付系统开发微信小程序端整个项目的源码结构清晰遵循了Flask最佳实践适合作为中级Python开发者的学习参考。在部署时需要注意做好定时备份和安全防护特别是患者隐私数据的保护。
企业数字化 ERP 产品动态
相关推荐
MATLAB蒙特卡洛元胞自动机模拟金属晶粒生长 1. 项目概述在材料科学研究中,晶粒组织的演变过程直接影响着金属材料的力学性能和服役行为。传统实验观察方法存在成本高、周期长、难以捕捉瞬时变化等局限。这个MATLAB模拟项目提供了一种经济高效的数值模拟方案,能够可视化展示不同条件下晶粒生长、相变… · 2026/9/21 22:52:13
C#中XML文件操作:XmlDocument与XDocument实战指南 1. XML文件操作在C#中的核心价值XML作为一种结构化数据存储格式,在C#开发中扮演着重要角色。无论是配置文件、数据交换还是Web服务,XML处理都是每个C#开发者必须掌握的技能。我处理过上百个XML文件后总结出:90%的XML操作场景都可以归结为四个… · 2026/9/26 0:23:53
不用等游戏更新:DLSS Swapper 切换 DLSS、FSR、XeSS 版本只需5分钟 不用等游戏更新:DLSS Swapper 切换 DLSS、FSR、XeSS 版本只需5分钟 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper
上周一个游戏推送更新后,新带进来的 DLSS dll 在我的显卡上画面出现闪烁&… · 2026/9/21 22:52:06
怎么用云虚拟主机建设网站:3步搞定模板丑闻的最佳实践 怎么用云虚拟主机建设网站:3步搞定模板丑闻的最佳实践 别再用那些丑得让人想删库的模板网站撑门面了!很多华南老板觉得网站嘛,能打开就行,结果客户一看这排版,直接划走。其实, 怎么用云虚拟主机建设网站 并不需要你是程序员,关键是找到 最佳实践… · 2026/9/27 14:37:50
3个真相揭秘:用帝国做网站怎么样及建站报价避坑指南 3个真相揭秘:用帝国做网站怎么样及建站报价避坑指南 自己不会代码想做网站,是不是光看那些花里胡哨的建站报价单就头大? 别急,先别被销售忽悠。 我干了10年建站,见过太多人花几千块买了个“皇帝的新衣”。… · 2026/9/27 14:37:50
郑州做网站推广多少钱?3步对比评测省下一半预算 郑州做网站推广多少钱?3步对比评测省下一半预算 刚来郑州想搞点副业,手里有预算但没技术,想给公司做个官网引流,结果一打听报价,从几千到几万都有,听得人脑仁疼。自己不会代码想做网站,却怕被外包公司当韭菜割,这时候搞个 对比评测… · 2026/9/27 14:37:44
成都网络营销公司从零搭建网站必看的5个安全坑 成都网络营销公司从零搭建网站必看的5个安全坑 上周刚帮一个做外贸的客户救火,他的网站首页突然弹出一堆乱七八糟的广告窗口,后台密码也莫名其妙改了。他问我:“成都网络营销公司做的站怎么这么快就挂了马?”我告诉他,这不是运气差,是底子没打好。很多… · 2026/9/27 14:37:44
资中网站建设避坑指南:5个关键注意事项与选型建议 资中网站建设避坑指南:5个关键注意事项与选型建议 找资中本地建站公司,最怕什么?不是代码写得烂,而是报价单上那行“定制开发”背后藏着的高价与隐形消费。很多老板觉得官网嘛,找个模板改改就行,结果一签约才发现,基础功能只给一半,想加个在线询盘还… · 2026/9/27 14:37:44
手把手教你在 VSCode 里用 TaoToken 配置 Maven 工程骨架(图文结合) /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/27 14:37:38
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01