使用Flask+MySQL构建健康体检记录管理系统

本文手把手教你搭建一个功能完整的健康体检记录管理系统,包含家庭成员管理、健康数据记录、统计分析等功能。

一、项目背景

随着人们对健康的重视程度不断提高,记录日常健康数据(如体重、血压、心率等)变得越来越重要。本文将介绍如何使用Python Flask框架和MySQL数据库,从零构建一个功能完整的健康体检记录管理系统。

技术栈

  • 后端框架:Flask 2.3.3(轻量级Web框架)

  • ORM框架:Flask-SQLAlchemy 3.1.1(数据库操作)

  • 表单处理:Flask-WTF 1.2.1 + WTForms 3.0.1

  • 数据库:MySQL 8.0

  • 数据库驱动:PyMySQL 1.1.0

二、系统架构设计

2.1 系统功能模块

健康体检记录系统
├── 用户/家庭成员管理
│   ├── 添加成员
│   ├── 编辑成员信息
│   ├── 查看成员详情
│   └── 删除成员
├── 健康记录管理
│   ├── 添加健康记录
│   ├── 编辑记录
│   ├── 删除记录
│   └── 按成员筛选记录
└── 统计分析
    ├── 健康指标统计
    ├── 趋势分析
    └── 历史数据对比

2.2 数据库设计

用户表(users)
字段名 类型 说明
id INT 主键,自增
name VARCHAR(50) 姓名
gender VARCHAR(10) 性别
birth_date DATETIME 出生日期
phone VARCHAR(20) 手机号
height INT 身高(cm)
avatar VARCHAR(10) 头像emoji
is_active BOOLEAN 是否启用
健康记录表(health_records)
字段名 类型 说明
id INT 主键,自增
user_id INT 外键,关联用户表
record_date DATETIME 记录日期
weight FLOAT 体重(kg)
systolic_bp INT 收缩压(mmHg)
diastolic_bp INT 舒张压(mmHg)
heart_rate INT 心率
sleep_hours FLOAT 睡眠时长
steps INT 步数

2.3 项目目录结构

health-webapp/
│
├── app.py              # 主应用文件(路由+视图函数)
├── config.py           # 配置文件(数据库连接等)
├── models.py           # 数据模型(数据库表定义)
├── forms.py            # 表单类(表单验证)
├── run.py              # 启动文件
│
├── templates/          # HTML模板目录
│   ├── base.html       # 基础模板
│   ├── index.html      # 首页
│   ├── users.html      # 用户列表
│   ├── user_detail.html # 用户详情
│   ├── user_form.html  # 用户表单
│   ├── records.html    # 健康记录列表
│   ├── record_form.html # 健康记录表单
│   └── statistics.html # 统计分析
│
└── static/             # 静态文件目录

三、核心代码实现

3.1 配置文件(config.py)

from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

db = SQLAlchemy()

class User(db.Model):
    __tablename__ = 'users'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), nullable=False)
    gender = db.Column(db.String(10))
    birth_date = db.Column(db.DateTime)
    phone = db.Column(db.String(20))
    height = db.Column(db.Integer)
    avatar = db.Column(db.String(10), default='👤')
    is_active = db.Column(db.Boolean, default=True)
    created_at = db.Column(db.DateTime, default=datetime.now)
    
    # 关系映射:一个用户有多条健康记录
    health_records = db.relationship('HealthRecord', back_populates='user', cascade='all, delete-orphan')
    
    def get_age(self):
        """计算年龄"""
        if self.birth_date:
            today = datetime.now()
            age = today.year - self.birth_date.year
            # 如果还没过生日,年龄减1
            if today.month < self.birth_date.month or \
               (today.month == self.birth_date.month and today.day < self.birth_date.day):
                age -= 1
            return age
        return None

class HealthRecord(db.Model):
    __tablename__ = 'health_records'
    
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    record_date = db.Column(db.DateTime, default=datetime.now, nullable=False)
    
    # 健康指标
    weight = db.Column(db.Float)          # 体重
    systolic_bp = db.Column(db.Integer)   # 收缩压
    diastolic_bp = db.Column(db.Integer)  # 舒张压
    heart_rate = db.Column(db.Integer)    # 心率
    blood_sugar = db.Column(db.Float)     # 血糖
    sleep_hours = db.Column(db.Float)     # 睡眠时长
    steps = db.Column(db.Integer)         # 步数
    note = db.Column(db.Text)             # 备注
    
    created_at = db.Column(db.DateTime, default=datetime.now)
    
    # 关系映射
    user = db.relationship('User', back_populates='health_records')
    
    def get_bmi(self):
        """计算BMI指数"""
        if self.weight and self.user and self.user.height:
            height_m = self.user.height / 100
            return round(self.weight / (height_m ** 2), 1)
        return None

关键设计说明:

  • 使用 relationship 建立一对多的关联关系

  • cascade='all, delete-orphan' 实现级联删除

  • 在模型中封装业务逻辑方法(如 get_age()get_bmi()

3.2 表单验证(forms.py)

from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField, FloatField, DateTimeField, SelectField, SubmitField
from wtforms.validators import DataRequired, Optional, NumberRange, Regexp

class UserForm(FlaskForm):
    name = StringField('姓名', validators=[DataRequired(message='请输入姓名')])
    gender = SelectField('性别', choices=[('', '请选择'), ('男', '男'), ('女', '女')])
    birth_date = DateTimeField('出生日期', format='%Y-%m-%d', validators=[Optional()])
    phone = StringField('手机号', validators=[Optional(), Regexp(r'^1[3-9]\d{9}$')])
    height = IntegerField('身高(cm)', validators=[Optional(), NumberRange(50, 300)])
    submit = SubmitField('保存')

表单验证器的使用:

  • DataRequired:必填字段验证

  • NumberRange:数值范围验证

  • Regexp:正则表达式验证(如手机号格式)

3.3 视图函数(app.py)

用户管理CRUD实现
@app.route('/users')
def users():
    """用户列表页"""
    all_users = User.query.filter_by(is_active=True).all()
    return render_template('users.html', users=all_users)

@app.route('/user/add', methods=['GET', 'POST'])
def add_user():
    """添加用户"""
    form = UserForm()
    if form.validate_on_submit():
        user = User(
            name=form.name.data,
            gender=form.gender.data,
            birth_date=form.birth_date.data,
            phone=form.phone.data,
            height=form.height.data,
            avatar=form.avatar.data
        )
        db.session.add(user)
        db.session.commit()
        flash(f'用户 {user.name} 添加成功!', 'success')
        return redirect(url_for('users'))
    return render_template('user_form.html', form=form, title='添加用户')
健康记录管理
@app.route('/record/add', methods=['GET', 'POST'])
def add_record():
    """添加健康记录"""
    form = HealthRecordForm()
    users = User.query.filter_by(is_active=True).all()
    
    if form.validate_on_submit():
        record = HealthRecord(
            user_id=request.form.get('user_id', type=int),
            record_date=form.record_date.data or datetime.now(),
            weight=form.weight.data,
            systolic_bp=form.systolic_bp.data,
            diastolic_bp=form.diastolic_bp.data,
            heart_rate=form.heart_rate.data,
            sleep_hours=form.sleep_hours.data,
            steps=form.steps.data,
            note=form.note.data
        )
        db.session.add(record)
        db.session.commit()
        flash('健康记录添加成功!', 'success')
        return redirect(url_for('records'))
    
    return render_template('record_form.html', form=form, users=users)

3.4 前端模板设计

使用Jinja2模板引擎,采用卡片式布局和响应式设计:

<!-- 基础模板 base.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>健康体检记录系统 - {% block title %}{% endblock %}</title>
    <style>
        /* 全局样式 */
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: 'Microsoft YaHei', Arial, sans-serif; background: #f0f2f5; }
        
        /* 渐变导航栏 */
        .navbar { 
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 
            color: white; 
            padding: 1rem 2rem; 
        }
        
        /* 卡片样式 */
        .card { 
            background: white; 
            border-radius: 12px; 
            box-shadow: 0 2px 8px rgba(0,0,0,0.1); 
            padding: 1.5rem; 
            margin-bottom: 1.5rem; 
        }
        
        /* 统计卡片 */
        .stat-card { 
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); 
            color: white; 
            padding: 1rem; 
            border-radius: 12px; 
            text-align: center; 
        }
    </style>
</head>
<body>
    <!-- 导航栏 -->
    <nav class="navbar">...</nav>
    
    <!-- 消息闪现 -->
    {% with messages = get_flashed_messages(with_categories=true) %}
        <!-- 显示消息 -->
    {% endwith %}
    
    <!-- 主要内容 -->
    <div class="container">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

四、关键技术点解析

4.1 ORM关系映射

# 一对多关系定义
class User(db.Model):
    health_records = db.relationship('HealthRecord', back_populates='user')

class HealthRecord(db.Model):
    user = db.relationship('User', back_populates='health_records')
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))

4.2 数据库会话管理

with app.app_context():
    db.create_all()  # 自动创建表

4.3 消息闪现(Flash Messages)

# 后端
flash(f'用户添加成功!', 'success')

# 前端
{% with messages = get_flashed_messages(with_categories=true) %}
    {% for category, message in messages %}
        <div class="alert alert-{{ category }}">{{ message }}</div>
    {% endfor %}
{% endwith %}

4.4 表单数据绑定与验证

# GET请求:显示表单并绑定已有数据
form = UserForm(obj=user)

# POST请求:验证并处理
if form.validate_on_submit():
    user.name = form.name.data
    db.session.commit()

4.5 URL参数传递与筛选

# 获取URL参数
user_id = request.args.get('user_id', type=int)

# 条件查询
if user_id:
    records = HealthRecord.query.filter_by(user_id=user_id).all()

五、运行与部署

5.1 环境准备

# 创建虚拟环境
python -m venv venv

# 激活虚拟环境
venv\Scripts\activate  # Windows
source venv/bin/activate  # Linux/Mac

# 安装依赖
pip install flask flask-sqlalchemy flask-wtf pymysql wtforms

5.2 配置文件设置

# config.py
class Config:
    SECRET_KEY = 'your-secret-key'
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:password@localhost/health_db'

5.3 启动应用

python run.py

访问 http://localhost:8000 即可使用系统。

六、项目亮点总结

  1. 完整的CRUD功能:实现了家庭成员和健康记录的增删改查

  2. 数据验证:使用WTForms进行前后端双重验证

  3. ORM设计:合理的数据模型设计和关系映射

  4. 响应式界面:纯CSS实现现代化UI,无需前端框架

  5. 代码分层:配置文件、模型、表单、视图分离,结构清晰

  6. 统计分析:自动计算BMI、平均指标等健康数据

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐