xiaji c4d307136a feat(report): 添加定时生成PDF报告功能并重构邮件发送任务
将PDF生成逻辑从邮件发送任务中分离,新增独立定时任务
更新README文档说明PDF生成配置和使用方法
2026-01-09 20:05:25 +08:00
2026-01-04 19:17:33 +08:00
2026-01-07 22:11:07 +08:00
2026-01-04 19:17:33 +08:00
2026-01-04 20:55:28 +08:00

家庭日报系统

专注于家庭生活的轻量级日报系统使用Django框架开发。

功能特性

  • 阅读记录管理(支持添加阅读笔记)
  • 感悟记录管理
  • 家庭事项管理(支持自定义事项类型)
  • 今日计划管理
  • 报告生成
  • 邮件发送
  • 后台管理界面(访问路径:/houtai

技术栈

  • Python 3.10+
  • Django 4.2+
  • Bootstrap 5
  • SQLite开发环境
  • PostgreSQL/MySQL生产环境
  • Gunicorn + Nginx生产部署

快速开始

安装依赖

pip install -r requirements.txt

运行开发服务器

python manage.py runserver

访问系统

打开浏览器访问:http://127.0.0.1:8000

数据库迁移指南

基本迁移流程

  1. 生成迁移文件:

    python manage.py makemigrations
    
  2. 查看迁移文件内容(重要!):

    cat core/migrations/000x_xxx.py
    
  3. 应用迁移:

    python manage.py migrate
    

当数据库有数据时增加字段

问题说明

当数据库中已有数据时通过Django的migrate命令增加新字段不会删除原有数据,但需要注意以下几点:

  1. 如果新字段设置为非空null=False, blank=False),则必须提供默认值,否则迁移会失败
  2. 如果新字段设置为可空null=True, blank=True则迁移会自动执行原有记录的新字段值为NULL

正确部署流程

  1. 在开发环境测试

    • 首先在开发环境生成迁移文件
    • 检查迁移文件内容,确保:
      • 新字段设置为可空(null=True, blank=True),或者
      • 新字段提供了合理的默认值
    • 在开发环境执行迁移,测试功能是否正常
  2. 备份生产数据库(重要!):

    # PostgreSQL示例
    pg_dump -U username -d dbname > backup_$(date +%Y%m%d_%H%M%S).sql
    
    # MySQL示例
    mysqldump -u username -p dbname > backup_$(date +%Y%m%d_%H%M%S).sql
    
  3. 在生产环境执行迁移

    # 进入项目目录
    cd /path/to/diary-family
    
    # 激活虚拟环境
    source venv/bin/activate
    
    # 生成迁移文件(如果在开发环境已生成,可跳过)
    python manage.py makemigrations
    
    # 应用迁移
    python manage.py migrate
    
  4. 验证迁移结果

    • 检查应用是否正常运行
    • 验证新功能是否可用
    • 检查数据是否完整

示例增加阅读笔记note字段

  1. 在模型中添加字段(core/models.py

    # 正确的做法:设置为可空字段
    note = models.TextField(blank=True, null=True, verbose_name="阅读笔记")
    
    # 或者:提供默认值
    note = models.TextField(default="", blank=True, verbose_name="阅读笔记")
    
  2. 生成迁移文件:

    python manage.py makemigrations
    
  3. 检查迁移文件,确保新字段设置正确:

    # 迁移文件示例0003_readingrecord_note.py
    class Migration(migrations.Migration):
        dependencies = [
            ('core', '0002_xxx'),
        ]
    
        operations = [
            migrations.AddField(
                model_name='readingrecord',
                name='note',
                field=models.TextField(blank=True, null=True, verbose_name='阅读笔记'),
            ),
        ]
    
  4. 应用迁移:

    python manage.py migrate
    

CSV数据导入指南

生成CSV文件

项目包含一个generate_import_csv.py脚本用于生成符合数据库表结构的CSV文件并导入数据。

  1. 生成CSV文件

    python generate_import_csv.py
    
  2. 生成的CSV文件

    • reading_type.csv - 阅读记录类型
    • insight_record.csv - 感悟记录
    • reading_record.csv - 阅读记录

CSV文件格式说明

reading_type.csv阅读记录类型

字段名 类型 说明
name 字符串 阅读类型名称(如:书籍、文章、论文等)

insight_record.csv感悟记录

字段名 类型 说明
date 日期 记录日期格式YYYY-MM-DD
content 文本 感悟内容

reading_record.csv阅读记录

字段名 类型 说明
date 日期 记录日期格式YYYY-MM-DD
type_id 整数 阅读类型ID关联reading_type表的id字段
title 字符串 阅读标题
source 字符串 阅读来源
progress 字符串 阅读进度(如:已完成、进行中、未开始)
note 文本 阅读笔记

自定义CSV数据

你可以手动编辑生成的CSV文件添加或修改数据然后再次运行导入脚本将数据导入到数据库。

数据导入

脚本会自动将CSV数据导入到数据库中导入流程

  1. 清空ReadingType表的现有数据避免类型ID冲突
  2. 导入ReadingType数据
  3. 导入InsightRecord数据
  4. 导入ReadingRecord数据

验证导入结果

可以使用Django shell查询数据库验证数据是否正确导入

python -c "import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'diary_family.settings'); import django; django.setup(); from core.models import ReadingType, InsightRecord, ReadingRecord; print('ReadingType数量:', ReadingType.objects.count()); print('InsightRecord数量:', InsightRecord.objects.count()); print('ReadingRecord数量:', ReadingRecord.objects.count()); print('ReadingType数据:', [rt.name for rt in ReadingType.objects.all()])"

生产部署

使用Gunicorn + Nginx

  1. 安装Gunicorn

    pip install gunicorn
    
  2. 启动Gunicorn

    gunicorn diary_family.wsgi:application --bind 0.0.0.0:8000
    
  3. 配置Nginx/etc/nginx/sites-available/diary-family

    server {
        listen 80;
        server_name example.com;
    
        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;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    
        location /static/ {
            alias /path/to/diary-family/static/;
        }
    
        location /media/ {
            alias /path/to/diary-family/media/;
        }
    }
    
  4. 启用Nginx配置

    ln -s /etc/nginx/sites-available/diary-family /etc/nginx/sites-enabled/
    systemctl restart nginx
    

常规代码更新流程

当需要更新代码时,可以使用以下命令:

cd /var/www/diary-family

# 1. 拉取远程最新代码(只获取,不合并)
git fetch origin

# 2. 硬重置本地分支到远程分支的最新版本(会覆盖所有本地未提交修改)
# 注意:将 main 替换为你的分支名(如 master、dev 等)
git reset --hard origin/main

# 3. 激活虚拟环境
source venv/bin/activate

# 4. 安装新依赖(如果有)
pip install -r requirements.txt

# 5. 收集静态文件(如果有静态文件更新)
python manage.py collectstatic --noinput

# 6. 重启服务
sudo supervisorctl restart all
sudo systemctl restart nginx

系统配置

在系统配置页面可以设置:

  • SMTP服务器信息
  • 邮件发送时间
  • 收件人邮箱

Celery 定时发送邮件任务配置

1. 邮件配置设置

在系统配置页面设置完邮件信息后,还需要在 Django 项目的 settings.py 中添加基础邮件配置:

# 邮件基础配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_PORT = 587  # 或根据你的 SMTP 服务器设置
EMAIL_USE_TLS = True  # 或根据你的 SMTP 服务器设置

2. 启动 Celery Worker 和 Beat

开发环境

# 启动 Celery Worker
celery -A diary_family worker -l info

# 启动 Celery Beat用于定时任务调度
celery -A diary_family beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler

生产环境

建议使用 supervisor 管理 Celery 进程。创建两个 supervisor 配置文件:

  1. celery_worker.conf

    [program:celery_worker]
    command=/path/to/venv/bin/celery -A diary_family worker -l info
    directory=/path/to/diary-family
    user=www-data
    group=www-data
    autostart=true
    autorestart=true
    stdout_logfile=/var/log/celery/worker.log
    stderr_logfile=/var/log/celery/worker_error.log
    
  2. celery_beat.conf

    [program:celery_beat]
    command=/path/to/venv/bin/celery -A diary_family beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
    directory=/path/to/diary-family
    user=www-data
    group=www-data
    autostart=true
    autorestart=true
    stdout_logfile=/var/log/celery/beat.log
    stderr_logfile=/var/log/celery/beat_error.log
    

启动 supervisor 服务:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start celery_worker
sudo supervisorctl start celery_beat

3. 配置定时任务

系统使用 django_celery_beat 进行定时任务管理,支持两种方式配置:

方式一:通过 Django 管理后台(推荐)

  1. 登录 Django 管理后台(/houtai
  2. 找到 Periodic tasks(周期性任务)
  3. 点击 Add 按钮添加新任务
  4. 配置任务:
    • Name: 任务名称(如:每日报告发送)
    • Task (registered): 选择 core.tasks.send_daily_report
    • Interval: 设置执行间隔(如:每天)
    • Enabled: 勾选启用
  5. 点击 Save 保存

方式二:通过代码配置

core/tasks.py 中添加定时任务配置:

from celery import shared_task
from django_celery_beat.models import PeriodicTask, IntervalSchedule

# 创建或更新定时任务
def setup_daily_report_task():
    # 创建每天执行的间隔
    schedule, created = IntervalSchedule.objects.get_or_create(
        every=1,
        period=IntervalSchedule.DAYS,
    )
    
    # 创建或更新定时任务
    task, created = PeriodicTask.objects.update_or_create(
        name='Daily Report Task',
        defaults={
            'interval': schedule,
            'task': 'core.tasks.send_daily_report',
        },
    )
    return task

然后在 Django 启动时调用此函数(如在 core/apps.py 中)。

4. 验证任务执行

  • 查看 Celery 日志:tail -f /var/log/celery/worker.log
  • 检查邮件是否正常发送
  • 在 Django 管理后台查看任务执行记录

5. 常见问题排查

  1. 任务不执行

    • 检查 Celery worker 和 beat 是否正常运行
    • 检查 Redis 服务是否正常
    • 检查任务是否已启用
    • 检查系统时间是否正确
  2. 邮件发送失败

    • 检查 SMTP 服务器配置是否正确
    • 检查邮箱账号密码是否正确
    • 检查收件人邮箱格式是否正确
    • 查看 Celery 日志中的错误信息
  3. 任务执行延迟

    • 检查系统负载是否过高
    • 考虑增加 Celery worker 数量
    • 检查 Redis 性能

6. 生产环境优化建议

  • 使用独立的 Redis 服务器
  • 配置合适的 worker 数量建议CPU 核心数 × 2
  • 定期清理 Celery 任务结果
  • 配置监控系统(如 Prometheus + Grafana
  • 启用 Celery 监控工具(如 Flower

定时生成PDF文件配置

除了定时发送邮件外系统还支持单独定时生成PDF文件便于在服务器上保存历史报告。

1. 配置定时生成PDF任务

方式一:通过 Django 管理后台(推荐)

  1. 登录 Django 管理后台(/houtai
  2. 找到 Periodic tasks(周期性任务)
  3. 点击 Add 按钮添加新任务
  4. 配置任务:
    • Name: 任务名称每日PDF报告生成
    • Task (registered): 选择 core.tasks.generate_daily_pdf_report
    • Interval: 设置执行间隔(如:每天)
    • Enabled: 勾选启用
  5. 点击 Save 保存

方式二:通过代码配置

core/tasks.py 中添加定时任务配置:

from celery import shared_task
from django_celery_beat.models import PeriodicTask, IntervalSchedule

# 创建或更新PDF生成定时任务
def setup_daily_pdf_task():
    # 创建每天执行的间隔
    schedule, created = IntervalSchedule.objects.get_or_create(
        every=1,
        period=IntervalSchedule.DAYS,
    )
    
    # 创建或更新定时任务
    task, created = PeriodicTask.objects.update_or_create(
        name='Daily PDF Generation Task',
        defaults={
            'interval': schedule,
            'task': 'core.tasks.generate_daily_pdf_report',
        },
    )
    return task

然后在 Django 启动时调用此函数(如在 core/apps.py 中)。

2. PDF文件存储位置

生成的PDF文件默认存储在项目的 reports 目录下,命名格式为 report_YYYY-MM-DD.pdf

可以在 settings.py 中修改存储位置:

# Reports files configuration
REPORTS_URL = '/reports/'
REPORTS_ROOT = BASE_DIR / 'reports'  # 可以修改为其他路径

3. 验证PDF生成任务

  • 查看 Celery 日志:tail -f /var/log/celery/worker.log
  • 检查PDF文件是否生成ls -la /path/to/diary-family/reports/
  • 在 Django 管理后台查看任务执行记录

4. 常见问题排查

  1. PDF生成失败

    • 检查 WeasyPrint 库是否正确安装:pip list | grep weasyprint
    • 检查系统字体是否完整PDF生成需要系统字体支持
    • 查看 Celery 日志中的错误信息
  2. 任务执行但没有生成文件

    • 检查 REPORTS_ROOT 目录权限:确保 Celery 进程有写入权限
    • 检查磁盘空间是否充足
    • 查看 Celery 日志中的详细信息
  3. PDF内容不完整

    • 检查模板文件 core/templates/core/report_pdf.html 是否完整
    • 确保所有依赖的 CSS 和图像资源都能正常访问

Celery 监控(可选)

使用 Flower 监控 Celery 任务:

# 安装 Flower
pip install flower

# 启动 Flower
celery -A diary_family flower --port=5555

访问 http://your-server:5555 查看任务监控界面。

注意事项

  1. 定期备份数据库
  2. 生产环境建议使用PostgreSQL或MySQL数据库
  3. 定期清理过期数据
  4. 保持依赖包更新

许可证

MIT License

Description
家庭的日常报告,包括阅读,体悟,运动,计划等等内容。
Readme 463 KiB
Languages
Python 56.4%
HTML 43.6%