feat: 添加CSV数据生成和导入功能
新增generate_import_csv.py脚本用于生成和导入测试数据 更新README.md添加CSV数据导入指南 生成3个CSV文件并实现自动导入功能
This commit is contained in:
60
README.md
60
README.md
@@ -143,6 +143,66 @@ python manage.py runserver
|
||||
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
|
||||
|
||||
231
generate_import_csv.py
Normal file
231
generate_import_csv.py
Normal file
@@ -0,0 +1,231 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
CSV生成和Django ORM导入脚本
|
||||
"""
|
||||
|
||||
import csv
|
||||
import os
|
||||
from pathlib import Path
|
||||
from datetime import date
|
||||
from faker import Faker
|
||||
from loguru import logger
|
||||
|
||||
# 初始化faker
|
||||
fake = Faker('zh_CN')
|
||||
|
||||
# 项目根目录
|
||||
BASE_DIR = Path(__file__).resolve().parent
|
||||
|
||||
# 设置Django环境
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'diary_family.settings')
|
||||
import django
|
||||
django.setup()
|
||||
|
||||
# 导入Django模型
|
||||
from core.models import ReadingType, InsightRecord, ReadingRecord
|
||||
|
||||
# 生成ReadingType CSV
|
||||
@logger.catch
|
||||
def generate_reading_type_csv():
|
||||
"""生成阅读记录类型CSV文件"""
|
||||
csv_path = BASE_DIR / 'reading_type.csv'
|
||||
|
||||
# 定义字段名,与数据库表字段一一对应
|
||||
fields = ['name']
|
||||
|
||||
# 生成模拟数据
|
||||
data = [
|
||||
['书籍'],
|
||||
['文章'],
|
||||
['论文'],
|
||||
['报告'],
|
||||
['其他']
|
||||
]
|
||||
|
||||
# 写入CSV文件
|
||||
with open(csv_path, 'w', newline='', encoding='utf-8') as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(fields)
|
||||
writer.writerows(data)
|
||||
|
||||
logger.info(f"生成ReadingType CSV文件成功: {csv_path}")
|
||||
return csv_path
|
||||
|
||||
# 生成InsightRecord CSV
|
||||
@logger.catch
|
||||
def generate_insight_record_csv():
|
||||
"""生成感悟记录CSV文件"""
|
||||
csv_path = BASE_DIR / 'insight_record.csv'
|
||||
|
||||
# 定义字段名,与数据库表字段一一对应
|
||||
fields = ['date', 'content']
|
||||
|
||||
# 生成模拟数据
|
||||
data = []
|
||||
for _ in range(10):
|
||||
record_date = fake.date_between(start_date='-30d', end_date='today')
|
||||
content = fake.paragraph(nb_sentences=3, variable_nb_sentences=True)
|
||||
data.append([record_date, content])
|
||||
|
||||
# 写入CSV文件
|
||||
with open(csv_path, 'w', newline='', encoding='utf-8') as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(fields)
|
||||
writer.writerows(data)
|
||||
|
||||
logger.info(f"生成InsightRecord CSV文件成功: {csv_path}")
|
||||
return csv_path
|
||||
|
||||
# 生成ReadingRecord CSV
|
||||
@logger.catch
|
||||
def generate_reading_record_csv():
|
||||
"""生成阅读记录CSV文件"""
|
||||
csv_path = BASE_DIR / 'reading_record.csv'
|
||||
|
||||
# 定义字段名,与数据库表字段一一对应
|
||||
fields = ['date', 'type_id', 'title', 'source', 'progress', 'note']
|
||||
|
||||
# 生成模拟数据
|
||||
data = []
|
||||
for _ in range(15):
|
||||
record_date = fake.date_between(start_date='-30d', end_date='today')
|
||||
type_id = fake.random_int(min=1, max=5) # 对应ReadingType的id
|
||||
title = fake.sentence(nb_words=5, variable_nb_words=True)
|
||||
source = fake.company()
|
||||
progress = fake.random_element(['已完成', '进行中', '未开始'])
|
||||
note = fake.paragraph(nb_sentences=2, variable_nb_sentences=True)
|
||||
data.append([record_date, type_id, title, source, progress, note])
|
||||
|
||||
# 写入CSV文件
|
||||
with open(csv_path, 'w', newline='', encoding='utf-8') as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow(fields)
|
||||
writer.writerows(data)
|
||||
|
||||
logger.info(f"生成ReadingRecord CSV文件成功: {csv_path}")
|
||||
return csv_path
|
||||
|
||||
# 导入ReadingType CSV到Django模型
|
||||
@logger.catch
|
||||
def import_reading_type_csv(csv_path):
|
||||
"""将阅读记录类型CSV导入到Django模型"""
|
||||
try:
|
||||
logger.info(f"开始导入 {csv_path} 到ReadingType模型")
|
||||
|
||||
# 清空现有数据
|
||||
ReadingType.objects.all().delete()
|
||||
logger.info("已清空现有ReadingType数据")
|
||||
|
||||
# 读取CSV文件并导入数据
|
||||
with open(csv_path, 'r', encoding='utf-8') as f:
|
||||
# 跳过表头
|
||||
next(f)
|
||||
|
||||
# 读取CSV数据并创建模型实例
|
||||
reader = csv.reader(f)
|
||||
reading_types = []
|
||||
for row in reader:
|
||||
name = row[0]
|
||||
reading_types.append(ReadingType(name=name))
|
||||
|
||||
# 批量创建
|
||||
ReadingType.objects.bulk_create(reading_types)
|
||||
|
||||
logger.info(f"导入成功,共插入 {len(reading_types)} 条记录")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"导入失败: {e}")
|
||||
|
||||
# 导入InsightRecord CSV到Django模型
|
||||
@logger.catch
|
||||
def import_insight_record_csv(csv_path):
|
||||
"""将感悟记录CSV导入到Django模型"""
|
||||
try:
|
||||
logger.info(f"开始导入 {csv_path} 到InsightRecord模型")
|
||||
|
||||
# 读取CSV文件并导入数据
|
||||
with open(csv_path, 'r', encoding='utf-8') as f:
|
||||
# 跳过表头
|
||||
next(f)
|
||||
|
||||
# 读取CSV数据并创建模型实例
|
||||
reader = csv.reader(f)
|
||||
insight_records = []
|
||||
for row in reader:
|
||||
record_date = row[0]
|
||||
content = row[1]
|
||||
insight_records.append(InsightRecord(date=record_date, content=content))
|
||||
|
||||
# 批量创建
|
||||
InsightRecord.objects.bulk_create(insight_records)
|
||||
|
||||
logger.info(f"导入成功,共插入 {len(insight_records)} 条记录")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"导入失败: {e}")
|
||||
|
||||
# 导入ReadingRecord CSV到Django模型
|
||||
@logger.catch
|
||||
def import_reading_record_csv(csv_path):
|
||||
"""将阅读记录CSV导入到Django模型"""
|
||||
try:
|
||||
logger.info(f"开始导入 {csv_path} 到ReadingRecord模型")
|
||||
|
||||
# 读取CSV文件并导入数据
|
||||
with open(csv_path, 'r', encoding='utf-8') as f:
|
||||
# 跳过表头
|
||||
next(f)
|
||||
|
||||
# 读取CSV数据并创建模型实例
|
||||
reader = csv.reader(f)
|
||||
reading_records = []
|
||||
for row in reader:
|
||||
record_date = row[0]
|
||||
type_id = int(row[1])
|
||||
title = row[2]
|
||||
source = row[3]
|
||||
progress = row[4]
|
||||
note = row[5]
|
||||
|
||||
# 确保type_id存在
|
||||
if ReadingType.objects.filter(id=type_id).exists():
|
||||
reading_records.append(ReadingRecord(
|
||||
date=record_date,
|
||||
type_id=type_id,
|
||||
title=title,
|
||||
source=source,
|
||||
progress=progress,
|
||||
note=note
|
||||
))
|
||||
else:
|
||||
logger.warning(f"跳过记录: 类型ID {type_id} 不存在")
|
||||
|
||||
# 批量创建
|
||||
ReadingRecord.objects.bulk_create(reading_records)
|
||||
|
||||
logger.info(f"导入成功,共插入 {len(reading_records)} 条记录")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"导入失败: {e}")
|
||||
|
||||
# 主函数
|
||||
@logger.catch
|
||||
def main():
|
||||
"""主函数"""
|
||||
logger.info("开始执行CSV生成和导入脚本")
|
||||
|
||||
# 生成CSV文件
|
||||
reading_type_csv = generate_reading_type_csv()
|
||||
insight_record_csv = generate_insight_record_csv()
|
||||
reading_record_csv = generate_reading_record_csv()
|
||||
|
||||
# 导入CSV到Django模型
|
||||
import_reading_type_csv(reading_type_csv)
|
||||
import_insight_record_csv(insight_record_csv)
|
||||
import_reading_record_csv(reading_record_csv)
|
||||
|
||||
logger.info("脚本执行完成")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
11
insight_record.csv
Normal file
11
insight_record.csv
Normal file
@@ -0,0 +1,11 @@
|
||||
date,content
|
||||
2025-12-25,包括其中电脑方式来源我的经济.次数我们中国无法.需要密码一直具有专业.
|
||||
2025-12-30,注册来自原因环境起来公司一个.
|
||||
2026-01-06,一切情况显示结果.也是单位问题表示电影觉得.一个增加今天增加之后记者语言.
|
||||
2025-12-31,深圳投资经营分析是否人民.因此首页国际因为一点威望之后.
|
||||
2025-12-21,世界如何生活空间研究.中心不会文章教育其中网站男人之间.社区记者如此而且都是由于.
|
||||
2025-12-28,成为发现电脑更新网络.登录需要基本出现技术.感觉中国功能单位因为语言.
|
||||
2025-12-23,标题准备决定.的话只有如此.拥有那么所有上海手机觉得.
|
||||
2025-12-24,为什产品孩子.怎么处理研究.语言人民的话研究.
|
||||
2025-12-29,提高在线环境.一样同时今天需要过程朋友各种.方面经营电影发布不会.
|
||||
2025-12-22,学生一切网络系列情况继续.详细只要的话今天希望.这些进入评论作者需要.
|
||||
|
22
logs/app.log
22
logs/app.log
@@ -4,3 +4,25 @@
|
||||
2026-01-04 19:10:41.211 | INFO | core.views:index:45 - 用户访问首页
|
||||
2026-01-04 19:11:02.642 | INFO | core.views:yesterday_records:73 - 用户访问昨日记录页面
|
||||
2026-01-04 19:15:44.290 | INFO | core.views:yesterday_records:73 - 用户访问昨日记录页面
|
||||
2026-01-07 22:54:04.870 | INFO | __main__:generate_reading_type_csv:52 - 生成ReadingType CSV文件成功: C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_type.csv
|
||||
2026-01-07 22:54:04.872 | INFO | __main__:generate_insight_record_csv:77 - 生成InsightRecord CSV文件成功: C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\insight_record.csv
|
||||
2026-01-07 22:54:04.873 | INFO | __main__:generate_reading_record_csv:106 - 生成ReadingRecord CSV文件成功: C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_record.csv
|
||||
2026-01-07 22:54:04.873 | INFO | __main__:import_reading_type_csv:114 - 开始导入 C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_type.csv 到ReadingType模型
|
||||
2026-01-07 22:54:04.875 | ERROR | __main__:import_reading_type_csv:138 - 导入失败: no such table: core_readingtype
|
||||
2026-01-07 22:54:04.875 | INFO | __main__:import_insight_record_csv:145 - 开始导入 C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\insight_record.csv 到InsightRecord模型
|
||||
2026-01-07 22:54:04.895 | ERROR | __main__:import_insight_record_csv:166 - 导入失败: no such table: core_insightrecord
|
||||
2026-01-07 22:54:04.895 | INFO | __main__:import_reading_record_csv:173 - 开始导入 C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_record.csv 到ReadingRecord模型
|
||||
2026-01-07 22:54:04.912 | ERROR | __main__:import_reading_record_csv:210 - 导入失败: no such table: core_readingtype
|
||||
2026-01-07 22:54:04.912 | INFO | __main__:main:228 - 脚本执行完成
|
||||
2026-01-07 22:54:27.118 | INFO | __main__:generate_reading_type_csv:52 - 生成ReadingType CSV文件成功: C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_type.csv
|
||||
2026-01-07 22:54:27.119 | INFO | __main__:generate_insight_record_csv:77 - 生成InsightRecord CSV文件成功: C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\insight_record.csv
|
||||
2026-01-07 22:54:27.120 | INFO | __main__:generate_reading_record_csv:106 - 生成ReadingRecord CSV文件成功: C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_record.csv
|
||||
2026-01-07 22:54:27.120 | INFO | __main__:import_reading_type_csv:114 - 开始导入 C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_type.csv 到ReadingType模型
|
||||
2026-01-07 22:54:27.123 | INFO | __main__:import_reading_type_csv:118 - 已清空现有ReadingType数据
|
||||
2026-01-07 22:54:27.127 | INFO | __main__:import_reading_type_csv:135 - 导入成功,共插入 5 条记录
|
||||
2026-01-07 22:54:27.128 | INFO | __main__:import_insight_record_csv:145 - 开始导入 C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\insight_record.csv 到InsightRecord模型
|
||||
2026-01-07 22:54:27.149 | INFO | __main__:import_insight_record_csv:163 - 导入成功,共插入 10 条记录
|
||||
2026-01-07 22:54:27.149 | INFO | __main__:import_reading_record_csv:173 - 开始导入 C:\Users\xiaji\Documents\个人文件夹\夏骥\diary-family\reading_record.csv 到ReadingRecord模型
|
||||
2026-01-07 22:54:27.170 | INFO | __main__:import_reading_record_csv:207 - 导入成功,共插入 15 条记录
|
||||
2026-01-07 22:54:27.171 | INFO | __main__:main:228 - 脚本执行完成
|
||||
2026-01-07 23:01:51.374 | INFO | core.views:index:45 - 用户访问首页
|
||||
|
||||
16
reading_record.csv
Normal file
16
reading_record.csv
Normal file
@@ -0,0 +1,16 @@
|
||||
date,type_id,title,source,progress,note
|
||||
2025-12-23,2,发生很多活动国内.,信诚致远信息有限公司,进行中,通过投资起来不会首页非常.
|
||||
2025-12-27,2,社区其实音乐其实设计.,新宇龙信息信息有限公司,未开始,标准次数主题进入应用支持不过.
|
||||
2025-12-13,2,帖子主要都是最后.,商软冠联科技有限公司,已完成,就是在线社会任何一下成为以及.男人看到点击日本相关.
|
||||
2025-12-23,5,地方由于完成有些.,立信电子信息有限公司,已完成,但是技术一样.
|
||||
2025-12-19,1,资源显示推荐免费.,九方网络有限公司,未开始,就是一次威望北京看到大小进入.
|
||||
2025-12-27,4,喜欢很多一些.,趋势传媒有限公司,已完成,正在网络其中能力处理必须.谢谢成为北京最后.
|
||||
2025-12-09,4,免费电脑手机分析而且.,浦华众城信息有限公司,未开始,论坛通过以后.
|
||||
2025-12-25,2,使用的人到了类别.,天益信息有限公司,未开始,部分由于质量因此到了最大.
|
||||
2025-12-12,5,来源一切到了.,凌云科技有限公司,已完成,这样必须包括游戏方法不同内容.分析地区一定公司.
|
||||
2025-12-19,5,网络合作有些.,新宇龙信息网络有限公司,已完成,为了各种同时.积分相关类型.
|
||||
2025-12-28,2,应该生产加入记者汽车系列.,维旺明传媒有限公司,已完成,相关的话主题工程世界手机.网站知道不同工程价格所以.
|
||||
2026-01-05,5,直接生产推荐城市.,万迅电脑科技有限公司,进行中,组织支持市场能力然后最新无法.
|
||||
2026-01-06,2,位置出来标题谢谢注意还有.,盟新信息有限公司,进行中,以及关于数据他的目前.
|
||||
2025-12-18,5,制作开发全部有些只有.,信诚致远网络有限公司,未开始,这么人民解决威望她的威望.经验客户无法一种.
|
||||
2026-01-03,5,看到完全最大的人企业这是.,太极传媒有限公司,已完成,由于希望标准有限中心更新以后.影响国际只要其他经济有关对于.
|
||||
|
6
reading_type.csv
Normal file
6
reading_type.csv
Normal file
@@ -0,0 +1,6 @@
|
||||
name
|
||||
书籍
|
||||
文章
|
||||
论文
|
||||
报告
|
||||
其他
|
||||
|
Reference in New Issue
Block a user