Files
diary-family/README.md

636 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 家庭日报系统
专注于家庭生活的轻量级日报系统使用Django框架开发。
## 功能特性
- 阅读记录管理(支持添加阅读笔记)
- 感悟记录管理
- 家庭事项管理(支持自定义事项类型)
- 今日计划管理
- 报告生成
- 邮件发送
- 后台管理界面(访问路径:/houtai
## 技术栈
- Python 3.10+
- Django 4.2+
- Bootstrap 5
- SQLite开发环境
- PostgreSQL/MySQL生产环境
- Gunicorn + Nginx生产部署
## 快速开始
### 安装依赖
```bash
pip install -r requirements.txt
```
### 运行开发服务器
```bash
python manage.py runserver
```
### 访问系统
打开浏览器访问http://127.0.0.1:8000
## 数据库迁移指南
### 基本迁移流程
1. 生成迁移文件:
```bash
python manage.py makemigrations
```
2. 查看迁移文件内容(重要!):
```bash
cat core/migrations/000x_xxx.py
```
3. 应用迁移:
```bash
python manage.py migrate
```
### 当数据库有数据时增加字段
#### 问题说明
当数据库中已有数据时通过Django的migrate命令增加新字段**不会删除原有数据**,但需要注意以下几点:
1. 如果新字段设置为**非空**`null=False, blank=False`),则必须提供默认值,否则迁移会失败
2. 如果新字段设置为**可空**`null=True, blank=True`则迁移会自动执行原有记录的新字段值为NULL
#### 正确部署流程
1. **在开发环境测试**
- 首先在开发环境生成迁移文件
- 检查迁移文件内容,确保:
- 新字段设置为可空(`null=True, blank=True`),或者
- 新字段提供了合理的默认值
- 在开发环境执行迁移,测试功能是否正常
2. **备份生产数据库**(重要!):
```bash
# 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. **在生产环境执行迁移**
```bash
# 进入项目目录
cd /path/to/diary-family
# 激活虚拟环境
source venv/bin/activate
# 生成迁移文件(如果在开发环境已生成,可跳过)
python manage.py makemigrations
# 应用迁移
python manage.py migrate
```
4. **验证迁移结果**
- 检查应用是否正常运行
- 验证新功能是否可用
- 检查数据是否完整
#### 示例增加阅读笔记note字段
1. 在模型中添加字段(`core/models.py`
```python
# 正确的做法:设置为可空字段
note = models.TextField(blank=True, null=True, verbose_name="阅读笔记")
# 或者:提供默认值
note = models.TextField(default="", blank=True, verbose_name="阅读笔记")
```
2. 生成迁移文件:
```bash
python manage.py makemigrations
```
3. 检查迁移文件,确保新字段设置正确:
```python
# 迁移文件示例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. 应用迁移:
```bash
python manage.py migrate
```
## CSV数据导入指南
### 生成CSV文件
项目包含一个`generate_import_csv.py`脚本用于生成符合数据库表结构的CSV文件并导入数据。
1. 生成CSV文件
```bash
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查询数据库验证数据是否正确导入
```bash
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
```bash
pip install gunicorn
```
2. 启动Gunicorn
```bash
gunicorn diary_family.wsgi:application --bind 0.0.0.0:8000
```
3. 配置Nginx`/etc/nginx/sites-available/diary-family`
```nginx
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配置
```bash
ln -s /etc/nginx/sites-available/diary-family /etc/nginx/sites-enabled/
systemctl restart nginx
```
## 常规代码更新流程
当需要更新代码时,可以使用以下命令:
退出虚拟环境
deactivate
```bash
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 中添加基础邮件配置:
```python
# 邮件基础配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_PORT = 587 # 或根据你的 SMTP 服务器设置
EMAIL_USE_TLS = True # 或根据你的 SMTP 服务器设置
```
### 2. 启动 Celery Worker 和 Beat
#### 开发环境
```bash
# 启动 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**
```ini
[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**
```ini
[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 服务:
```bash
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` 中添加定时任务配置:
```python
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. 日志文件不存在问题解决方法
如果在生产服务器上执行 `tail -f /var/log/celery/worker.log` 时提示 `No such file or directory`,请按照以下步骤解决:
#### 步骤1检查日志目录是否存在
```bash
# 检查日志目录是否存在
ls -la /var/log/celery/
# 如果目录不存在,创建目录
sudo mkdir -p /var/log/celery/
# 设置正确的权限(确保 Celery 进程用户有读写权限)
sudo chown -R www-data:www-data /var/log/celery/
sudo chmod -R 755 /var/log/celery/
```
#### 步骤2检查 Supervisor 配置
确保 Supervisor 配置文件中指定的日志路径正确,并且 Celery 进程用户对该路径有读写权限。
#### 步骤3重启 Supervisor 和 Celery
```bash
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart celery_worker celery_beat
```
### 6. 试运行周期任务
当设置一个周期任务后,您可以通过以下方式试运行任务,而不需要等待到指定的时间:
#### 方式1通过 Django 管理后台
1. 登录 Django 管理后台(/houtai
2. 找到 **Periodic tasks**(周期性任务)
3. 选择您创建的任务
4. 点击页面底部的 **Run Task** 按钮立即执行任务
#### 方式2通过命令行
```bash
# 直接调用任务函数(同步执行)
python manage.py shell -c "from core.tasks import generate_daily_pdf_report; generate_daily_pdf_report()"
# 或者使用 Celery 命令行工具
celery -A diary_family call core.tasks.generate_daily_pdf_report
```
#### 方式3使用测试脚本
项目提供了一个测试脚本,用于验证 Celery 任务是否可以正常运行:
```bash
# 运行测试脚本
python test_celery.py
```
### 7. 常见错误和解决方法
#### 错误1日志文件不存在
**错误信息**`tail: cannot open '/var/log/celery/worker.log' for reading: No such file or directory`
**解决方法**
- 按照步骤5中的说明创建日志目录并设置正确权限
- 检查 Supervisor 配置中的日志路径是否正确
- 重启 Supervisor 和 Celery 服务
#### 错误2Celery 无法连接到 Redis
**错误信息**`redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused.`
**解决方法**
- 检查 Redis 服务是否正常运行:`sudo systemctl status redis-server`
- 启动 Redis 服务:`sudo systemctl start redis-server`
- 检查 Redis 配置是否允许本地连接
#### 错误3任务执行失败
**错误信息**`Task core.tasks.generate_daily_pdf_report[xxx] raised unexpected: Exception(...)`
**解决方法**
- 查看详细日志:`tail -f /var/log/celery/worker.log`
- 检查任务代码中的错误
- 确保所有依赖库都已正确安装
- 检查相关服务如数据库、Redis是否正常运行
#### 错误4PDF 生成失败
**错误信息**`WeasyPrint库不可用无法生成PDF报告`
**解决方法**
- 安装 WeasyPrint 库:`pip install weasyprint`
- 对于 Ubuntu 系统,可能需要安装系统依赖:
```bash
sudo apt-get install -y libpango-1.0-0 libpangoft2-1.0-0
```
### 8. 常见问题排查
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` 中添加定时任务配置:
```python
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` 中修改存储位置:
```python
# 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 任务:
```bash
# 安装 Flower
pip install flower
# 启动 Flower
celery -A diary_family flower --port=5555
```
访问 http://your-server:5555 查看任务监控界面。
## 注意事项
1. 定期备份数据库
2. 生产环境建议使用PostgreSQL或MySQL数据库
3. 定期清理过期数据
4. 保持依赖包更新
## 许可证
MIT License