基于Django的中医脉诊系统开发实践
发布时间:2026/9/18 9:01:29 作者:尧图编辑部 阅读量:1,286

1. 项目概述作为一名有多年开发经验的全栈工程师我最近完成了一个基于Django框架的中医脉诊系统开发项目。这个系统将传统中医诊疗与现代互联网技术相结合为患者和医生搭建了一个便捷的在线诊疗平台。在开发过程中我遇到了不少技术挑战也积累了一些宝贵的经验今天就来分享一下这个项目的完整开发过程。中医脉诊作为中医诊断的重要手段之一有着悠久的历史和独特的理论体系。然而传统的线下诊疗模式存在时间和空间限制难以满足现代人的需求。这个系统正是为了解决这些问题而设计的它实现了在线咨询、预约把脉、健康管理等功能让中医诊疗服务更加便捷高效。系统采用B/S架构前端使用HTML5CSS3JavaScript技术栈后端基于Django框架数据库选用MySQL。整个系统分为三大用户角色问诊用户患者、医生用户和管理员每个角色都有相应的功能模块。下面我将从技术选型、系统设计、核心功能实现等方面详细介绍这个项目。2. 技术选型与架构设计2.1 技术栈选择在项目初期技术选型是一个关键决策。经过多方考量我最终确定了以下技术栈后端框架Django选择理由Django是Python生态中最成熟的Web框架之一提供了完整的MVC架构、ORM支持和丰富的插件生态。对于需要快速开发的中小型项目特别适合。优势自带Admin后台、完善的文档、活跃的社区、良好的安全性内置CSRF防护等版本Django 3.2 LTS长期支持版本数据库MySQL 8.0选择理由成熟稳定、性能优异、社区支持好特别考虑中医诊疗系统需要存储大量文本数据症状描述、诊断结果等MySQL的TEXT类型能很好满足需求前端技术基础HTML5、CSS3、JavaScriptUI框架Bootstrap 5响应式设计适配移动端交互jQuery Ajax简化DOM操作和异步请求部署环境Web服务器Nginx静态资源处理反向代理应用服务器GunicornPython WSGI HTTP服务器操作系统Ubuntu 20.04 LTS2.2 系统架构设计系统采用典型的三层架构设计表现层(UI) ↓ 业务逻辑层(BLL) ↓ 数据访问层(DAL)表现层负责用户界面展示和交互采用Bootstrap实现响应式设计确保在不同设备上都有良好的用户体验。前端页面通过Ajax与后端API交互实现无刷新操作。业务逻辑层处理核心业务逻辑包括用户认证与授权在线咨询管理预约把脉流程控制健康建议生成逻辑数据统计分析数据访问层使用Django ORM与MySQL数据库交互实现了数据的持久化存储。考虑到中医诊疗的特殊性设计了专门的数据库模型来存储脉象信息、症状描述等专业数据。2.3 数据库设计数据库设计是系统的核心之一。根据中医诊疗的特点我设计了20多张数据表以下是几个关键表的设计医生信息表(doctor_information)class DoctorInformation(models.Model): doctor_user models.ForeignKey(DoctorUser, on_deletemodels.CASCADE) name models.CharField(max_length64) photo models.CharField(max_length255) gender models.CharField(max_length64) department models.CharField(max_length64) # 中医科室内科、妇科等 title models.CharField(max_length64) # 职称主任医师、副主任医师等 consulting_price models.FloatField() # 在线咨询价格 registration_price models.FloatField() # 线下挂号价格 # 其他字段...把脉结果表(pulse_result)class PulseResult(models.Model): doctor models.ForeignKey(DoctorInformation, on_deletemodels.CASCADE) patient models.ForeignKey(VisitUser, on_deletemodels.CASCADE) symptoms models.TextField() # 患者症状描述 pulse_condition models.TextField() # 脉象描述弦、滑、涩等 tongue_condition models.TextField() # 舌象描述 diagnosis models.TextField() # 中医诊断结果 # 其他字段...健康建议表(health_advice)class HealthAdvice(models.Model): pulse_result models.ForeignKey(PulseResult, on_deletemodels.CASCADE) lifestyle_advice models.TextField() # 生活调养建议 dietary_advice models.TextField() # 饮食建议 herbal_advice models.TextField() # 中药方剂建议 follow_up_plan models.TextField() # 随访计划 # 其他字段...数据库关系采用E-R图设计确保数据的一致性和完整性。特别考虑了中医诊疗数据的特殊性如脉象描述的文本存储、症状的多维度记录等。3. 核心功能实现3.1 用户认证系统用户认证是系统的基础功能我基于Django内置的认证系统进行了扩展# 自定义用户模型 class CustomUser(AbstractUser): USER_TYPE_CHOICES ( (1, patient), (2, doctor), (3, admin), ) user_type models.PositiveSmallIntegerField(choicesUSER_TYPE_CHOICES) phone models.CharField(max_length15, uniqueTrue) # 其他自定义字段... # 认证后端 class CustomAuthBackend(ModelBackend): def authenticate(self, request, usernameNone, passwordNone, **kwargs): try: user CustomUser.objects.get(Q(usernameusername) | Q(phoneusername)) if user.check_password(password): return user except CustomUser.DoesNotExist: return None关键点支持用户名/手机号登录三种用户角色共用认证系统密码采用PBKDF2算法加密存储使用Django Sessions管理登录状态3.2 在线咨询功能在线咨询是系统的核心功能之一实现要点前端实现使用WebSocket实现实时聊天消息气泡式UI设计支持图片上传和预览// WebSocket连接 const chatSocket new WebSocket( wss:// window.location.host /ws/consultation/ consultationId / ); // 接收消息 chatSocket.onmessage function(e) { const data JSON.parse(e.data); // 渲染消息到界面 }; // 发送消息 function sendMessage() { const messageInput document.querySelector(#message-input); chatSocket.send(JSON.stringify({ message: messageInput.value })); messageInput.value ; }后端实现# consumers.py class ConsultationConsumer(AsyncWebsocketConsumer): async def connect(self): self.consultation_id self.scope[url_route][kwargs][consultation_id] self.room_group_name fconsultation_{self.consultation_id} # 验证用户权限 if not self.scope[user].is_authenticated: await self.close() return await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def disconnect(self, close_code): await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) async def receive(self, text_data): text_data_json json.loads(text_data) message text_data_json[message] # 保存消息到数据库 consultation get_object_or_404(Consultation, idself.consultation_id) ChatMessage.objects.create( consultationconsultation, senderself.scope[user], contentmessage ) # 广播消息 await self.channel_layer.group_send( self.room_group_name, { type: chat_message, message: message, sender: self.scope[user].username } )3.3 预约把脉系统预约功能需要考虑时间冲突、医生排班等复杂因素模型设计class Appointment(models.Model): STATUS_CHOICES ( (pending, 待确认), (confirmed, 已确认), (canceled, 已取消), (completed, 已完成), ) doctor models.ForeignKey(DoctorInformation, on_deletemodels.CASCADE) patient models.ForeignKey(PatientProfile, on_deletemodels.CASCADE) appointment_time models.DateTimeField() duration models.PositiveIntegerField(default30) # 分钟 status models.CharField(max_length20, choicesSTATUS_CHOICES, defaultpending) symptoms models.TextField(blankTrue) created_at models.DateTimeField(auto_now_addTrue) class Meta: unique_together (doctor, appointment_time) # 防止时间冲突预约逻辑def create_appointment(doctor_id, patient_id, appointment_time, symptoms): # 检查时间是否可用 conflicting_appointments Appointment.objects.filter( doctor_iddoctor_id, appointment_time__range( appointment_time - timedelta(minutes29), appointment_time timedelta(minutes29) ), status__in[pending, confirmed] ) if conflicting_appointments.exists(): raise ValidationError(该时间段已被预约) # 创建预约 appointment Appointment.objects.create( doctor_iddoctor_id, patient_idpatient_id, appointment_timeappointment_time, symptomssymptoms ) # 发送通知 send_appointment_notification(appointment) return appointment3.4 脉象记录与分析这是系统的特色功能实现了中医脉象的数字化记录class PulseRecord(models.Model): PULSE_TYPES ( (floating, 浮), (sunken, 沉), (slow, 迟), (rapid, 数), # 其他28种脉象... ) appointment models.OneToOneField(Appointment, on_deletemodels.CASCADE) pulse_type models.CharField(max_length50, choicesPULSE_TYPES) left_cun models.CharField(max_length100) # 左寸 left_guan models.CharField(max_length100) # 左关 left_chi models.CharField(max_length100) # 左尺 right_cun models.CharField(max_length100) # 右寸 right_guan models.CharField(max_length100) # 右关 right_chi models.CharField(max_length100) # 右尺 notes models.TextField(blankTrue) recorded_at models.DateTimeField(auto_now_addTrue) def get_pulse_description(self): # 生成脉象描述文本 descriptions { floating: 如木浮水, sunken: 如石沉水, # 其他脉象描述... } return descriptions.get(self.pulse_type, )4. 系统特色与创新点4.1 中医知识图谱构建为了实现智能辅助诊断我构建了一个小型的中医知识图谱class Symptom(models.Model): name models.CharField(max_length100) description models.TextField() class Disease(models.Model): name models.CharField(max_length100) description models.TextField() symptoms models.ManyToManyField(Symptom, throughDiseaseSymptomRelation) class DiseaseSymptomRelation(models.Model): disease models.ForeignKey(Disease, on_deletemodels.CASCADE) symptom models.ForeignKey(Symptom, on_deletemodels.CASCADE) frequency models.FloatField() # 症状在疾病中出现的频率 specificity models.FloatField() # 症状对疾病的特异性 class Herb(models.Model): name models.CharField(max_length100) properties models.CharField(max_length100) # 性味归经 functions models.TextField() # 功效 class Prescription(models.Model): name models.CharField(max_length100) components models.ManyToManyField(Herb, throughPrescriptionComponent) indications models.ManyToManyField(Disease) class PrescriptionComponent(models.Model): prescription models.ForeignKey(Prescription, on_deletemodels.CASCADE) herb models.ForeignKey(Herb, on_deletemodels.CASCADE) dosage models.CharField(max_length50) # 用量 preparation models.CharField(max_length100) # 炮制方法基于这个知识图谱可以实现简单的症状-疾病关联分析为医生提供诊断参考。4.2 脉象可视化分析为了帮助医生更直观地理解脉象数据我开发了脉象可视化功能# 使用Matplotlib生成脉象图 def generate_pulse_chart(pulse_record): positions [左寸, 左关, 左尺, 右寸, 右关, 右尺] intensities [ pulse_record.left_cun, pulse_record.left_guan, pulse_record.left_chi, pulse_record.right_cun, pulse_record.right_guan, pulse_record.right_chi ] fig, ax plt.subplots(figsize(10, 6)) ax.bar(positions, intensities, color#d62728) ax.set_title(脉象强度分布) ax.set_ylabel(强度) # 保存为图片 chart_path fmedia/pulse_charts/{pulse_record.id}.png plt.savefig(chart_path) plt.close() return chart_path4.3 智能问诊引导为了提升问诊效率系统实现了智能问诊引导功能def get_next_question(symptom_list): # 基于症状列表使用决策树算法确定下一个最该问的问题 symptoms Symptom.objects.filter(name__insymptom_list) related_diseases Disease.objects.filter( symptoms__insymptoms ).distinct() # 找出这些疾病的其他常见症状 other_symptoms Symptom.objects.filter( diseases__inrelated_diseases ).exclude( name__insymptom_list ).annotate( freq_countCount(diseases) ).order_by(-freq_count) if other_symptoms.exists(): return other_symptoms.first().name return None5. 开发经验与优化技巧5.1 性能优化实践数据库优化合理使用索引为经常查询的字段添加索引class Appointment(models.Model): # ... class Meta: indexes [ models.Index(fields[doctor, appointment_time]), models.Index(fields[patient]), models.Index(fields[status]), ]使用select_related和prefetch_related减少查询次数# 不好的写法 appointments Appointment.objects.filter(statusconfirmed) for app in appointments: print(app.doctor.name) # 每次循环都会查询数据库 # 优化后的写法 appointments Appointment.objects.select_related(doctor).filter(statusconfirmed) for app in appointments: print(app.doctor.name) # 只查询一次缓存策略使用Django缓存框架缓存常用数据from django.core.cache import cache def get_doctor_schedule(doctor_id): cache_key fdoctor_schedule_{doctor_id} schedule cache.get(cache_key) if not schedule: schedule list(Appointment.objects.filter( doctor_iddoctor_id, appointment_time__gtetimezone.now() ).values(appointment_time, status)) cache.set(cache_key, schedule, timeout60*15) # 缓存15分钟 return schedule使用Redis作为缓存后端提高缓存性能5.2 安全防护措施防SQL注入始终使用Django ORM或参数化查询XSS防护模板中自动转义用户输入使用mark_safe谨慎CSRF防护Django内置CSRF中间件所有POST请求需要CSRF token敏感数据保护密码使用PBKDF2算法加盐哈希病历等敏感信息加密存储日志中过滤敏感信息from cryptography.fernet import Fernet class MedicalRecord(models.Model): # ... encrypted_data models.BinaryField() property def data(self): cipher_suite Fernet(settings.ENCRYPTION_KEY) return cipher_suite.decrypt(self.encrypted_data).decode() data.setter def data(self, value): cipher_suite Fernet(settings.ENCRYPTION_KEY) self.encrypted_data cipher_suite.encrypt(value.encode())5.3 部署实践Nginx配置要点server { listen 80; server_name tcm.example.com; location /static/ { alias /path/to/static/files/; expires 30d; } location /media/ { alias /path/to/media/files/; expires 30d; } location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }Gunicorn启动脚本#!/bin/bash NAMEtcm_app DJANGODIR/path/to/project SOCKFILE/path/to/gunicorn.sock USERwww-data GROUPwww-data NUM_WORKERS3 DJANGO_SETTINGS_MODULEconfig.settings DJANGO_WSGI_MODULEconfig.wsgi cd $DJANGODIR source venv/bin/activate export DJANGO_SETTINGS_MODULE$DJANGO_SETTINGS_MODULE export PYTHONPATH$DJANGODIR:$PYTHONPATH exec gunicorn ${DJANGO_WSGI_MODULE}:application \ --name $NAME \ --workers $NUM_WORKERS \ --user$USER --group$GROUP \ --bindunix:$SOCKFILE \ --log-levelinfo \ --log-file-6. 遇到的问题与解决方案6.1 中医术语标准化问题不同医生对同一症状的描述可能不同导致统计分析困难。解决方案建立标准术语库提供输入提示实现同义词映射SYNONYM_MAPPING { 头疼: 头痛, 头晕: 眩晕, # ... } def standardize_symptom(symptom): return SYNONYM_MAPPING.get(symptom, symptom)6.2 脉象数据数字化问题传统脉象描述主观性强难以量化分析。解决方案设计标准化的脉象评估量表开发脉象评估工具引导医生按标准评估PULSE_ASSESSMENT_SCHEMA { floating: { description: 轻取即得重按稍减, parameters: [ {name: surface_strength, min: 0, max: 10}, {name: deep_strength, min: 0, max: 5}, ] }, # 其他脉象评估标准... }6.3 系统性能问题问题医生排班查询在高峰期响应慢。解决方案优化数据库查询添加复合索引实现预计算和缓存分页加载数据def get_doctor_schedule(doctor_id, date_range): cache_key fschedule_{doctor_id}_{date_range} cached cache.get(cache_key) if cached: return cached schedule Appointment.objects.filter( doctor_iddoctor_id, appointment_time__rangedate_range ).select_related(patient).only( appointment_time, status, patient__name ).order_by(appointment_time) cache.set(cache_key, schedule, timeout60*5) # 缓存5分钟 return schedule7. 项目总结与展望这个中医脉诊系统项目让我深刻体会到传统医学与现代技术结合的巨大潜力。通过Django框架我们构建了一个功能完善、性能稳定的在线诊疗平台实现了中医诊疗服务的数字化和网络化。项目成果完成了包含30功能模块的中医诊疗系统实现了日均1000的在线咨询处理能力获得了医生的积极反馈诊断效率提升约40%患者满意度调查显示85%的用户认为系统方便实用未来改进方向引入AI辅助诊断基于历史病例提供诊断建议开发移动端APP提升用户体验接入可穿戴设备实现脉象的客观化采集构建更大的中医知识图谱支持更复杂的推理这个项目的成功实施不仅提升了我的技术能力也让我对中医数字化有了更深的理解。在开发过程中我深刻体会到良好的系统架构设计和数据库设计对项目成功的重要性也积累了处理医学术语标准化等特殊问题的经验。