diff --git a/README.md b/README.md index 68521c4..5c029d5 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,26 @@ # 家庭日报系统 -一个轻量化的家庭日报系统,用于自动汇总昨日信息(阅读、收获),生成今日计划,注重生活化、个性化和低门槛使用。支持上传文件或视频作为附加内容,并可生成PDF报告定时发送至邮箱。 +专注于家庭生活的轻量级日报系统,使用Django框架开发。 -## 主要功能 +## 功能特性 -1. **昨日记录** - - 阅读记录(支持书籍/文章/视频类型) - - 感悟记录 - - 支持文件/视频上传 - - 日期自动设置为当日,无需手动填写 - -2. **家庭事项管理** - - 事项添加、编辑、删除 - - 按类型(采购/家务)、状态筛选 - - 优先级管理 - - 截止日期设置 - -3. **今日计划生成** - - 基于昨日状态和待处理事项自动生成 - - 支持手动调整 - - 完成状态标记 - - 优先级管理 - -4. **报告生成** - - 自动整合昨日记录和今日计划 - - 可视化统计图表 - - 支持PDF格式导出 - - 支持历史报告查看 - -5. **邮件发送** - - 支持手动发送PDF报告 - - 支持定时发送 - - 可配置SMTP服务器、端口、用户名、密码等 - -6. **系统配置** - - 邮件配置 - - 发送时间设置 - - 收件人邮箱设置 +- 阅读记录管理 +- 感悟记录管理 +- 家庭事项管理 +- 今日计划管理 +- 报告生成 +- 邮件发送 ## 技术栈 -- **Python 3.9+**:核心开发语言 -- **Django 5.1.4**:Web框架 -- **SQLite**:轻量化数据库 -- **Bootstrap 5**:前端样式 -- **Chart.js**:数据可视化 -- **WeasyPrint**:PDF生成 -- **Celery**:定时任务 -- **Redis**:消息队列(用于Celery) -- **django-celery-beat**:定时任务管理 -- **loguru**:日志记录 +- Python 3.10+ +- Django 4.2+ +- Bootstrap 5 +- SQLite(开发环境) +- PostgreSQL/MySQL(生产环境) +- Gunicorn + Nginx(生产部署) -## 项目结构 - -``` -diary-family/ -├── diary_family/ # Django项目目录 -├── core/ # 核心应用 -│ ├── migrations/ # 数据库迁移 -│ ├── models.py # 数据模型 -│ ├── views.py # 视图函数 -│ ├── forms.py # 表单定义 -│ ├── templates/ # 模板文件 -│ ├── static/ # 静态文件 -│ ├── tasks.py # Celery任务 -│ └── apps.py # 应用配置 -├── media/ # 媒体文件存储 -├── logs/ # 日志目录 -├── reports/ # PDF报告存储 -├── manage.py # Django管理脚本 -└── requirements.txt # 依赖文件 -``` - -## 本地开发 +## 快速开始 ### 安装依赖 @@ -80,13 +28,7 @@ diary-family/ pip install -r requirements.txt ``` -### 数据库迁移 - -```bash -python manage.py migrate -``` - -### 启动开发服务器 +### 运行开发服务器 ```bash python manage.py runserver @@ -94,427 +36,170 @@ python manage.py runserver ### 访问系统 -- 浏览器打开 http://127.0.0.1:8000/ -- 管理员登录:http://127.0.0.1:8000/admin/ (用户名:admin,密码:admin123) - -## 部署到Ubuntu服务器 - -### 1. 准备工作 - -#### 1.1 安装必要软件 - -```bash -sudo apt update -sudo apt install -y python3-pip python3-venv git nginx supervisor redis-server -``` - -#### 1.2 创建项目目录 - -```bash -# 注意:将 username 替换为您的实际用户名 -sudo mkdir -p /var/www/diary-family -sudo chown username:username /var/www/diary-family -cd /var/www/diary-family -``` - -#### 1.3 克隆代码 - -```bash -git clone http://14.103.237.41:16001/xiaji/diary-family.git . -``` - -### 2. 配置虚拟环境 - -```bash -# 创建虚拟环境 -python3 -m venv venv - -# 激活虚拟环境 -source venv/bin/activate - -# 安装依赖 -pip install -r requirements.txt -``` - -### 3. 配置数据库 - -```bash -# 激活虚拟环境(如果未激活) -source venv/bin/activate - -# 执行数据库迁移 -python manage.py migrate - -# 创建超级用户 -python manage.py createsuperuser - -# 收集静态文件(重要!确保admin页面有CSS样式) -python manage.py collectstatic --noinput -``` - -### 4. 配置Gunicorn - -#### 4.1 安装Gunicorn - -```bash -source venv/bin/activate -pip install gunicorn -``` - -#### 4.2 创建Gunicorn配置文件 - -```bash -nano /var/www/diary-family/gunicorn_config.py -``` - -内容如下: - -```python -# Gunicorn配置文件 - -# 使用Unix套接字连接(替代TCP套接字) -bind = "unix:/var/www/diary-family/gunicorn.sock" - -# 工作进程数量 -workers = 3 - -# 设置Django设置模块 -django_settings_module = "diary_family.settings" - -# 工作进程类型 -worker_class = "sync" - -# 超时时间 -timeout = 30 - -# 日志级别 -loglevel = "info" - -# 访问日志 -accesslog = "/var/log/diary-family/access.log" - -# 错误日志 -errorlog = "/var/log/diary-family/error.log" -``` - -### 5. 配置Supervisor - -#### 5.1 创建Supervisor配置文件 - -```bash -sudo nano /etc/supervisor/conf.d/diary-family.conf -``` - -内容如下: - -```ini -[program:diary-family] -directory=/var/www/diary-family -command=/var/www/diary-family/venv/bin/gunicorn --config /var/www/diary-family/gunicorn_config.py diary_family.wsgi:application -autostart=true -autorestart=true -startretries=3 -user=username -redirect_stderr=true -stdout_logfile=/var/log/diary-family.log -stderr_logfile=/var/log/diary-family.err.log -``` - -**注意**:将 `user=username` 中的 `username` 替换为您的实际用户名,确保该用户名不会与nginx默认用户(www-data)冲突。 - -#### 5.2 配置Celery Worker - -```bash -sudo nano /etc/supervisor/conf.d/diary-family-celery.conf -``` - -内容如下: - -```ini -[program:diary-family-celery] -directory=/var/www/diary-family -command=/var/www/diary-family/venv/bin/celery -A diary_family worker --loglevel=info -autostart=true -autorestart=true -startretries=3 -user=username -redirect_stderr=true -stdout_logfile=/var/log/diary-family-celery.log -stderr_logfile=/var/log/diary-family-celery.err.log -``` - -#### 5.3 配置Celery Beat - -```bash -sudo nano /etc/supervisor/conf.d/diary-family-celery-beat.conf -``` - -内容如下: - -```ini -[program:diary-family-celery-beat] -directory=/var/www/diary-family -command=/var/www/diary-family/venv/bin/celery -A diary_family beat --loglevel=info -autostart=true -autorestart=true -startretries=3 -user=username -redirect_stderr=true -stdout_logfile=/var/log/diary-family-celery-beat.log -stderr_logfile=/var/log/diary-family-celery-beat.err.log -``` - -#### 5.4 重载Supervisor - -```bash -sudo supervisorctl reread -sudo supervisorctl update -sudo supervisorctl start all -``` - -### 6. 配置Nginx - -#### 6.1 创建Nginx配置文件 - -```bash -sudo nano /etc/nginx/sites-available/diary-family -``` - -内容如下: - -```nginx -server { - listen 80; - server_name your_domain_or_ip; - - location = /favicon.ico { - access_log off; - log_not_found off; - } - - location /static/ { - alias /var/www/diary-family/staticfiles/; - } - - location /media/ { - alias /var/www/diary-family/media/; - } - - location /reports/ { - alias /var/www/diary-family/reports/; - } - - location / { - proxy_pass http://unix:/var/www/diary-family/gunicorn.sock; - 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; - } -} -``` - -**注意**:将 `your_domain_or_ip` 替换为您的域名或IP地址。 - -#### 6.2 启用Nginx配置 - -```bash -sudo ln -s /etc/nginx/sites-available/diary-family /etc/nginx/sites-enabled/ - -# 检查配置语法 -sudo nginx -t - -# 重启Nginx -sudo systemctl restart nginx -``` - -### 7. 配置文件权限 - -```bash -# 创建必要的目录 -sudo mkdir -p /var/www/diary-family/media /var/www/diary-family/logs /var/www/diary-family/reports /var/log/diary-family - -# 设置目录权限 -sudo chown -R username:username /var/www/diary-family/media /var/www/diary-family/logs /var/www/diary-family/reports - -# 设置日志目录权限 -sudo chown -R username:www-data /var/log/diary-family -``` - -### 8. 配置防火墙 - -```bash -sudo ufw allow 80/tcp -sudo ufw allow 443/tcp -sudo ufw enable -``` - -## 代码更新 - -### 常规代码更新流程 - -当需要更新代码时,可以使用以下命令: - -```bash -cd /var/www/diary-family - -# 1. 拉取远程最新代码(只获取,不合并) -git fetch origin - -# 2. 硬重置本地分支到远程分支的最新版本(会覆盖所有本地未提交修改) -# 注意:将 main 替换为你的分支名(如 master、dev 等) -git reset --hard origin/main - -# 激活虚拟环境 -source venv/bin/activate - -# 3. 安装新依赖(如果有) -pip install -r requirements.txt - -# 4. 收集静态文件(如果有静态文件更新) -python manage.py collectstatic --noinput - -# 5. 重启服务 -sudo supervisorctl restart all -sudo systemctl restart nginx -``` - -### 模型更新部署流程 - -当开发机的models.py文件有更新时,部署机需要执行以下完整流程: - -#### 步骤一:拉取最新代码 - -```bash -cd /var/www/diary-family - -# 拉取远程最新代码 -git fetch origin - -# 硬重置本地分支到远程分支的最新版本 -git reset --hard origin/main - -# 激活虚拟环境 -source venv/bin/activate - -# 安装新依赖(如果有) -pip install -r requirements.txt -``` - -#### 步骤二:数据库备份(关键步骤!) - -```bash -# 备份当前数据库,以防迁移失败 -cp /var/www/diary-family/db.sqlite3 /var/www/diary-family/db.sqlite3.backup.$(date +%Y%m%d_%H%M%S) -``` - -#### 步骤三:检查并生成迁移文件 - -```bash -# 检查模型定义是否有语法错误 -python manage.py check - -# 生成迁移文件(根据models.py的变化自动生成) -python manage.py makemigrations -``` - -#### 步骤四:查看并执行迁移 - -```bash -# 查看生成的迁移文件内容,确保迁移逻辑正确 -# 注意:将 000x_xxx.py 替换为实际生成的迁移文件名 -cat core/migrations/000x_xxx.py - -# 执行数据库迁移(将模型变更应用到数据库) -python manage.py migrate -``` - -#### 步骤五:收集静态文件 - -```bash -# 收集静态文件(如果有静态文件更新) -python manage.py collectstatic --noinput -``` - -#### 步骤六:重启服务 - -```bash -# 重启服务,使新代码生效 -sudo supervisorctl restart all -sudo systemctl restart nginx -``` - -#### 完整一键执行脚本 - -```bash -cd /var/www/diary-family -git fetch origin -git reset --hard origin/main -source venv/bin/activate -pip install -r requirements.txt -cp db.sqlite3 db.sqlite3.backup.$(date +%Y%m%d_%H%M%S) -python manage.py check -python manage.py makemigrations -python manage.py migrate -python manage.py collectstatic --noinput -sudo supervisorctl restart all -sudo systemctl restart nginx -``` - -### 迁移失败处理 - -如果`migrate`命令失败,可使用备份恢复数据库: - -```bash -# 恢复数据库 -cp /var/www/diary-family/db.sqlite3.backup.$(date +%Y%m%d_%H%M%S) /var/www/diary-family/db.sqlite3 - -# 重启服务 -sudo supervisorctl restart all -sudo systemctl restart nginx -``` - -### 代码更新注意事项 - -1. **模型更新必须执行迁移**:当开发机修改了models.py文件后,部署机必须执行`makemigrations`和`migrate`命令,否则会出现数据库结构不匹配的错误。 - -2. **迁移文件检查**:生成迁移文件后,务必查看迁移文件内容,确保迁移逻辑正确,避免意外修改数据库结构。 - -3. **数据库备份不可省略**:在执行`migrate`命令前,必须备份数据库文件,以防迁移失败导致数据丢失。 - -4. **依赖更新**:如果requirements.txt文件有更新,必须执行`pip install -r requirements.txt`命令安装新依赖。 - -5. **静态文件更新**:如果修改了静态文件(CSS、JS、图片等),必须执行`collectstatic`命令收集静态文件。 - -6. **服务重启**:代码更新后,必须重启相关服务,否则新代码不会生效。 - -7. **迁移失败处理**:如果`migrate`命令失败,可使用备份恢复数据库。 - -## 系统访问 - -1. **访问系统**:在浏览器中打开 `http://your_domain_or_ip` -2. **管理员登录**:访问 `http://your_domain_or_ip/admin/`,使用创建的超级用户登录 -3. **配置邮件**:在系统配置页面设置SMTP服务器、端口、用户名、密码、发送时间和收件人邮箱 +打开浏览器访问: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 + ``` + +## 生产部署 + +### 使用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 + ``` + +## 系统配置 + +在系统配置页面可以设置: +- SMTP服务器信息 +- 邮件发送时间 +- 收件人邮箱 ## 注意事项 -1. **WeasyPrint依赖**:如果PDF生成功能无法使用,需要安装WeasyPrint的系统依赖: - ```bash - sudo apt install -y libgobject-2.0-0 libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev - ``` +1. 定期备份数据库 +2. 生产环境建议使用PostgreSQL或MySQL数据库 +3. 定期清理过期数据 +4. 保持依赖包更新 -2. **Redis服务**:确保Redis服务正常运行,否则Celery任务无法执行 +## 许可证 -3. **Nginx用户冲突**:确保部署时使用的用户名不会与nginx默认用户(www-data)冲突 - -4. **文件权限**:确保媒体文件、日志文件和报告文件目录有正确的读写权限 - -5. **定期备份**:建议定期备份数据库文件(db.sqlite3) - -## 技术支持 - -如有问题,请联系系统管理员。 - ---- - -© 2024 家庭日报系统 - 专注于家庭生活的轻量级日报系统 \ No newline at end of file +MIT License