1. 项目背景与核心价值
作为一名长期从事Web开发的工程师,我最近用Django框架完成了一个宠物信息管理系统的开发。这个系统最初是为本地一家宠物医院设计的,经过多次迭代后已经成为一个功能完善、可复用的解决方案。相比市面上通用的CRM系统,这套系统针对宠物行业的特点做了深度定制,特别适合中小型宠物诊所、宠物店或流浪动物救助站使用。
系统最核心的价值在于将宠物医疗、寄养、美容等业务场景中的关键信息数字化。举个例子,当一只宠物首次就诊时,工作人员可以快速录入它的品种、年龄、疫苗记录、过敏史等信息。这些数据不仅方便后续服务,还能生成健康报告提醒主人下次疫苗时间。我见过太多宠物店还在用Excel表格管理客户信息,每次查找记录都要浪费好几分钟。
2. 系统架构与技术选型
2.1 为什么选择Django
选择Django作为基础框架主要基于三个考量:首先是它的"开箱即用"特性,自带Admin后台、ORM和用户认证系统,这让我节省了至少40%的开发时间;其次是Python生态中有大量生物医学相关的数据分析库,方便后期扩展健康预测功能;最后是Django的MTV模式让前端和后端开发可以并行进行。
这里特别提一下Django ORM的优势。在宠物医疗场景中,经常需要处理复杂的多表查询,比如"找出所有未绝育的成年犬类宠物"。用原生SQL写这种查询会很痛苦,而Django ORM只需要这样:
Pet.objects.filter( species='dog', age__gte=2, is_neutered=False ).select_related('owner')2.2 数据库设计要点
系统使用PostgreSQL作为数据库,主要表结构包括:
宠物核心表:
- 基础信息:名字、品种、出生日期、芯片号
- 医疗信息:绝育状态、血型、既往病史
- 关系字段:主人外键、兽医外键
医疗记录表:
- 就诊日期、症状描述、诊断结果
- 用药记录(多对多关联药品表)
- 下次复查提醒日期
服务预约表:
- 服务类型(美容、寄养、医疗)
- 时间窗口管理
- 工作人员分配
在设计疫苗记录字段时,我采用了JSONField来存储动态的疫苗清单。这是因为不同品种的宠物需要接种的疫苗种类和频率差异很大,固定字段难以满足需求。例如:
vaccination_records = models.JSONField(default=list) # 示例存储结构 [{ "name": "狂犬疫苗", "date": "2023-05-10", "next_due": "2024-05-01", "verified": True }]3. 核心功能实现细节
3.1 智能提醒系统
这是客户最满意的功能之一。系统会扫描数据库中的各类时间节点,自动触发三种提醒:
- 疫苗提醒:根据宠物年龄和上次接种时间,提前两周通知主人
- 用药提醒:对于需要长期服药的宠物,每天推送用药通知
- 复诊提醒:基于诊断记录中的医嘱生成
实现的关键在于Django的Celery定时任务结合PostgreSQL的窗口函数。比如查询即将到期疫苗的代码:
from django.db.models import F, Window from django.db.models.functions import Lag reminders = Pet.objects.annotate( prev_vaccine_date=Window( expression=Lag('vaccination_records__date'), partition_by=['owner'], order_by=F('vaccination_records__date').desc() ) ).filter( vaccination_records__next_due__lte=timezone.now() + timedelta(days=14) )3.2 多角色权限控制
系统设计了四种角色权限:
- 前台:基础信息录入、预约管理
- 兽医:医疗记录读写、处方开具
- 管理员:全系统配置
- 宠物主人:通过微信小程序查看自家宠物信息
权限控制主要通过Django-guardian实现对象级权限。比如确保兽医只能修改自己负责的宠物记录:
@permission_required_or_403('change_pet', (Pet, 'id', 'pet_id')) def update_medical_record(request, pet_id): # 只有对该pet有修改权限的用户才能进入4. 前端交互优化技巧
4.1 宠物档案页性能优化
当宠物档案页需要同时显示基本信息、医疗历史、消费记录等多个维度的数据时,初期版本出现了严重的N+1查询问题。通过以下措施将页面加载时间从3.2秒降到了400ms:
- 使用
select_related和prefetch_related优化关联查询 - 对医疗记录采用分页加载(每页10条)
- 高频更新的疫苗状态使用Redis缓存
def get_pet_detail(pet_id): pet = Pet.objects.select_related( 'owner', 'primary_vet' ).prefetch_related( Prefetch('medical_records', queryset=MedicalRecord.objects.order_by('-visit_date')[:10]), 'vaccination_records' ).get(id=pet_id)4.2 图片处理最佳实践
宠物照片管理系统有几个特殊需求:
- 需要为每张照片自动生成缩略图
- 支持主人上传多张生活照
- 医疗照片需要加密存储
我使用Django-storages配合AWS S3实现文件存储,用Pillow进行图片处理。关键配置:
# settings.py DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' AWS_S3_FILE_OVERWRITE = False AWS_QUERYSTRING_AUTH = False # models.py def pet_photo_upload(instance, filename): return f"pets/{instance.pet.id}/photos/{uuid.uuid4().hex[:8]}_{filename}" class PetPhoto(models.Model): pet = models.ForeignKey(Pet, on_delete=models.CASCADE) photo = models.ImageField(upload_to=pet_photo_upload) is_medical = models.BooleanField(default=False)5. 部署与运维经验
5.1 生产环境配置
系统采用Docker-compose部署,主要服务包括:
- Django应用(Gunicorn运行)
- PostgreSQL数据库
- Redis缓存
- Celery worker
- Nginx反向代理
最重要的经验是合理设置数据库连接池。宠物医院早上开业时经常会有集中查询,默认配置会导致连接耗尽。解决方案是在DATABASES配置中添加:
'OPTIONS': { 'connection_timeout': 5, 'max_connections': 100, 'stale_timeout': 300 }5.2 数据备份策略
医疗数据丢失会造成严重后果,我们实现了三重备份:
- PostgreSQL每日全量备份到AWS S3
- 关键表变更通过Django-signals实时写入审计日志
- 每周生成XML格式的数据快照供客户本地保存
备份脚本通过Django-crontab定时运行:
from django_crontab import CronJobBase, Schedule class BackupJob(CronJobBase): schedule = Schedule(run_every_mins=1440) # 每天 code = 'petcare.backup_job' def do(self): call_command('dbbackup') call_command('mediabackup')6. 常见问题排查指南
6.1 疫苗提醒未触发
这是最常被反馈的问题,通常有三个原因:
时区配置错误
检查settings.py中的TIME_ZONE和USE_TZ设置,确保与服务器时区一致Celery beat未运行
使用命令确认beat进程状态:systemctl status celery-beatJSON字段查询语法错误
正确的疫苗到期查询应该使用:Pet.objects.filter( vaccination_records__contains=[{ "next_due": str(date.today()) }] )
6.2 照片上传失败
主要排查路径:
- 检查S3存储桶的CORS配置
- 确认IAM角色有PutObject权限
- 验证文件大小是否超过
DATA_UPLOAD_MAX_MEMORY_SIZE限制
建议在表单中添加实时验证:
// 前端验证示例 document.getElementById('photo').addEventListener('change', function(e) { if(this.files[0].size > 10 * 1024 * 1024) { alert('文件大小不能超过10MB'); this.value = ''; } });7. 扩展与二次开发建议
系统预留了几个扩展接口:
微信小程序集成
通过Django REST framework暴露API,小程序端使用JWT认证健康数据分析
使用Pandas分析医疗记录,预测常见疾病风险智能硬件对接
预留了IoT设备接口,可接入智能喂食器、宠物摄像头等设备
一个实用的扩展案例是通过机器学习分析宠物体重变化:
from sklearn.linear_model import LinearRegression def predict_weight(pet_id): records = WeightRecord.objects.filter(pet_id=pet_id) X = [[i] for i in range(len(records))] y = [r.weight for r in records] model = LinearRegression().fit(X, y) return model.predict([[len(X) + 30]])[0] # 预测30天后体重在开发这类系统时,最重要的是保持数据结构的灵活性。宠物行业的业务需求变化很快,今天可能只需要记录疫苗信息,明天客户可能就要增加美容服务记录。我的经验是:所有主要模型都预留1-2个JSONField,核心关系使用外键而非硬编码,这样系统才能适应不同机构的个性化需求。