文档相关功能
This commit is contained in:
parent
a90d31c420
commit
5eb4ccd7fd
59
deploy.ps1
59
deploy.ps1
@ -1,59 +0,0 @@
|
||||
# 确保在项目根目录下执行此脚本
|
||||
|
||||
# 7-Zip路径 - 请根据实际安装位置修改
|
||||
$7zipPath = "D:\7zip\7-Zip\7z.exe" # 原始路径
|
||||
# $7zipPath = "C:\Program Files\7-Zip\7z.exe" # 修改后的路径
|
||||
|
||||
# 创建临时部署目录
|
||||
New-Item -Path "deploy_temp" -ItemType Directory -Force
|
||||
|
||||
# 复制整个项目目录到临时目录
|
||||
Copy-Item -Path "role_based_system" -Destination "deploy_temp\" -Recurse -Force
|
||||
Copy-Item -Path "user_management" -Destination "deploy_temp\" -Recurse -Force
|
||||
Copy-Item -Path "manage.py" -Destination "deploy_temp\" -Force
|
||||
Copy-Item -Path "requirements.txt" -Destination "deploy_temp\" -Force
|
||||
Copy-Item -Path "*.md" -Destination "deploy_temp\" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
# 移除不需要的文件和目录
|
||||
Get-ChildItem -Path "deploy_temp" -Recurse -Filter "__pycache__" -Directory | Remove-Item -Recurse -Force
|
||||
Get-ChildItem -Path "deploy_temp" -Recurse -Filter "*.pyc" | Remove-Item -Force
|
||||
|
||||
# 特别排除不需要的目录
|
||||
$excludeDirs = @(
|
||||
".git", ".idea", ".vscode",
|
||||
"venv", ".venv", "env", "__pycache__", "migrations"
|
||||
)
|
||||
|
||||
foreach ($dir in $excludeDirs) {
|
||||
Get-ChildItem -Path "deploy_temp" -Recurse -Directory -Filter $dir |
|
||||
Where-Object { $_.FullName -notmatch "\\migrations\\__pycache__" } |
|
||||
Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# 保留migrations目录但删除其中的pyc文件
|
||||
if (Test-Path "deploy_temp\user_management\migrations") {
|
||||
Get-ChildItem -Path "deploy_temp\user_management\migrations" -Filter "*.pyc" | Remove-Item -Force
|
||||
Get-ChildItem -Path "deploy_temp\user_management\migrations" -Directory -Filter "__pycache__" | Remove-Item -Recurse -Force
|
||||
}
|
||||
|
||||
# 排除不需要的文件
|
||||
$excludeFiles = @(
|
||||
"*.pyc", "*.pyo", "*.pyd", "*.so", "*.dll",
|
||||
"*.db", "*.sqlite3", "*.log", "*.zip", "*.tar.gz",
|
||||
"local_settings.py", "*.bak"
|
||||
)
|
||||
|
||||
foreach ($pattern in $excludeFiles) {
|
||||
Get-ChildItem -Path "deploy_temp" -Recurse -Filter $pattern | Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
|
||||
# 使用7-Zip打包
|
||||
& $7zipPath a -ttar knowledge_system.tar ".\deploy_temp\*"
|
||||
& $7zipPath a -tgzip knowledge_system.tar.gz knowledge_system.tar
|
||||
|
||||
# 清理临时文件
|
||||
Remove-Item -Path "knowledge_system.tar" -Force
|
||||
Remove-Item -Path "deploy_temp" -Recurse -Force
|
||||
|
||||
Write-Host "部署包已创建: knowledge_system.tar.gz" -ForegroundColor Green
|
124
feishu/feishu.py
124
feishu/feishu.py
@ -2,6 +2,8 @@ import json
|
||||
import django
|
||||
import os
|
||||
import sys
|
||||
import pandas as pd
|
||||
from django.db import transaction
|
||||
|
||||
# 设置 Django 环境
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
@ -30,7 +32,7 @@ def extract_field_value(field_value):
|
||||
return field_value
|
||||
|
||||
def save_to_database(record):
|
||||
"""保存记录到数据库"""
|
||||
"""从飞书多维表格保存记录到数据库"""
|
||||
fields = record.fields
|
||||
record_id = record.record_id
|
||||
|
||||
@ -57,7 +59,7 @@ def save_to_database(record):
|
||||
'system_categories': extract_field_value(fields.get('系统展示的带货品类', [])),
|
||||
'actual_categories': extract_field_value(fields.get('实际高播放量带货品类', [])),
|
||||
'human_categories': fields.get('达人标想要货品类', ''),
|
||||
'creator_base': '', # 如果有这个字段,添加相应的处理
|
||||
'creator_base': '',
|
||||
'notes': extract_field_value(fields.get('父记录', '')),
|
||||
}
|
||||
|
||||
@ -131,7 +133,92 @@ def fetch_all_records(client, app_token, table_id, user_access_token):
|
||||
print(f"最终获取到 {len(total_records)} 条记录")
|
||||
return total_records
|
||||
|
||||
def main():
|
||||
def update_from_excel(excel_file_path):
|
||||
"""从Excel文件更新数据库记录"""
|
||||
try:
|
||||
print(f"开始读取Excel文件: {excel_file_path}")
|
||||
df = pd.read_excel(excel_file_path)
|
||||
|
||||
if 'Handle' not in df.columns:
|
||||
print("错误: Excel文件中缺少'Handle'列")
|
||||
return
|
||||
|
||||
update_count = 0
|
||||
skip_count = 0
|
||||
error_count = 0
|
||||
|
||||
# 获取可更新的字段列表
|
||||
excluded_fields = {'id', 'record_id', 'created_at', 'updated_at'}
|
||||
model_fields = {f.name for f in FeishuCreator._meta.get_fields()} - excluded_fields
|
||||
valid_columns = set(df.columns) & model_fields
|
||||
|
||||
print(f"可更新的列: {valid_columns}")
|
||||
|
||||
with transaction.atomic():
|
||||
for index, row in df.iterrows():
|
||||
try:
|
||||
handle = str(row['Handle']).strip()
|
||||
if not handle:
|
||||
print(f"跳过第{index+2}行: Handle为空")
|
||||
skip_count += 1
|
||||
continue
|
||||
|
||||
# 查找现有记录
|
||||
creator = FeishuCreator.objects.filter(handle=handle).first()
|
||||
if not creator:
|
||||
print(f"跳过Handle为'{handle}'的记录: 数据库中不存在")
|
||||
skip_count += 1
|
||||
continue
|
||||
|
||||
# 准备更新数据
|
||||
update_data = {}
|
||||
for column in valid_columns:
|
||||
if column == 'Handle':
|
||||
continue
|
||||
|
||||
value = row[column]
|
||||
if pd.isna(value):
|
||||
continue
|
||||
|
||||
# 处理特殊类型
|
||||
if isinstance(value, (list, dict)):
|
||||
value = json.dumps(value)
|
||||
elif isinstance(value, (int, float)):
|
||||
if column in ['fans_count']:
|
||||
value = int(value)
|
||||
else:
|
||||
value = str(value)
|
||||
else:
|
||||
value = str(value).strip()
|
||||
|
||||
if value:
|
||||
update_data[column] = value
|
||||
|
||||
# 更新记录
|
||||
if update_data:
|
||||
for field, value in update_data.items():
|
||||
setattr(creator, field, value)
|
||||
creator.save()
|
||||
update_count += 1
|
||||
print(f"已更新Handle为'{handle}'的记录")
|
||||
else:
|
||||
skip_count += 1
|
||||
print(f"跳过Handle为'{handle}'的记录: 无需更新")
|
||||
|
||||
except Exception as e:
|
||||
error_count += 1
|
||||
print(f"处理Handle'{handle}'时出错: {str(e)}")
|
||||
|
||||
print("\nExcel更新完成!统计信息:")
|
||||
print(f"更新记录数:{update_count}")
|
||||
print(f"跳过记录数:{skip_count}")
|
||||
print(f"错误记录数:{error_count}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"处理Excel文件时出错: {str(e)}")
|
||||
|
||||
def sync_from_feishu():
|
||||
"""从飞书多维表格同步数据"""
|
||||
# 创建client
|
||||
client = lark.Client.builder() \
|
||||
.enable_set_token(True) \
|
||||
@ -143,15 +230,13 @@ def main():
|
||||
TABLE_ID = "tbl3oikG3F8YYtVA"
|
||||
USER_ACCESS_TOKEN = "u-ecM5BmzKx4uHz3sG0FouQSk1l9kxgl_3Xa00l5Ma24Jy"
|
||||
|
||||
# 获取所有记录
|
||||
print("开始获取所有记录...")
|
||||
print("开始从飞书同步数据...")
|
||||
all_records = fetch_all_records(client, APP_TOKEN, TABLE_ID, USER_ACCESS_TOKEN)
|
||||
|
||||
if not all_records:
|
||||
print("未获取到任何记录")
|
||||
return
|
||||
|
||||
# 更新数据库
|
||||
print("\n开始更新数据库...")
|
||||
created_count = 0
|
||||
updated_count = 0
|
||||
@ -162,7 +247,7 @@ def main():
|
||||
if creator:
|
||||
if created:
|
||||
created_count += 1
|
||||
if created_count % 10 == 0: # 每10条才打印一次,避免输出过多
|
||||
if created_count % 10 == 0:
|
||||
print(f"已创建 {created_count} 条记录...")
|
||||
else:
|
||||
updated_count += 1
|
||||
@ -172,13 +257,34 @@ def main():
|
||||
error_count += 1
|
||||
print(f"处理记录失败")
|
||||
|
||||
# 打印统计信息
|
||||
print("\n更新完成!统计信息:")
|
||||
print("\n飞书同步完成!统计信息:")
|
||||
print(f"新建记录:{created_count}")
|
||||
print(f"更新记录:{updated_count}")
|
||||
print(f"错误记录:{error_count}")
|
||||
print(f"总记录数:{len(all_records)}")
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
if len(sys.argv) < 2:
|
||||
print("使用方法:")
|
||||
print("1. 从飞书同步: python feishu.py sync")
|
||||
print("2. 从Excel更新: python feishu.py excel <excel文件路径>")
|
||||
return
|
||||
|
||||
command = sys.argv[1]
|
||||
|
||||
if command == 'sync':
|
||||
sync_from_feishu()
|
||||
elif command == 'excel':
|
||||
if len(sys.argv) != 3:
|
||||
print("使用方法: python feishu.py excel <excel文件路径>")
|
||||
return
|
||||
excel_file_path = sys.argv[2]
|
||||
update_from_excel(excel_file_path)
|
||||
else:
|
||||
print("无效的命令。使用方法:")
|
||||
print("1. 从飞书同步: python feishu.py sync")
|
||||
print("2. 从Excel更新: python feishu.py excel <excel文件路径>")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
35
user_management/migrations/0004_knowledgebasedocument.py
Normal file
35
user_management/migrations/0004_knowledgebasedocument.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Generated by Django 5.1.5 on 2025-03-31 14:03
|
||||
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user_management', '0003_alter_feishucreator_handle'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='KnowledgeBaseDocument',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('document_id', models.CharField(max_length=100, verbose_name='文档ID')),
|
||||
('document_name', models.CharField(max_length=255, verbose_name='文档名称')),
|
||||
('external_id', models.CharField(max_length=100, verbose_name='外部文档ID')),
|
||||
('status', models.CharField(choices=[('active', '有效'), ('deleted', '已删除')], default='active', max_length=20, verbose_name='状态')),
|
||||
('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||
('update_time', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
|
||||
('knowledge_base', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='kb_documents', to='user_management.knowledgebase', verbose_name='知识库')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '知识库文档',
|
||||
'verbose_name_plural': '知识库文档',
|
||||
'db_table': 'knowledge_base_documents',
|
||||
'indexes': [models.Index(fields=['knowledge_base', 'status'], name='knowledge_b_knowled_a4db1b_idx'), models.Index(fields=['document_id'], name='knowledge_b_documen_dab90f_idx'), models.Index(fields=['external_id'], name='knowledge_b_externa_b0060c_idx')],
|
||||
'unique_together': {('knowledge_base', 'document_id')},
|
||||
},
|
||||
),
|
||||
]
|
@ -669,3 +669,41 @@ class FeishuCreator(models.Model):
|
||||
db_table = 'feishu_creators'
|
||||
verbose_name = '创作者数据'
|
||||
verbose_name_plural = '创作者数据'
|
||||
|
||||
class KnowledgeBaseDocument(models.Model):
|
||||
"""知识库文档关联模型"""
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
knowledge_base = models.ForeignKey(
|
||||
'KnowledgeBase',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='kb_documents',
|
||||
verbose_name='知识库'
|
||||
)
|
||||
document_id = models.CharField(max_length=100, verbose_name='文档ID')
|
||||
document_name = models.CharField(max_length=255, verbose_name='文档名称')
|
||||
external_id = models.CharField(max_length=100, verbose_name='外部文档ID')
|
||||
status = models.CharField(
|
||||
max_length=20,
|
||||
default='active',
|
||||
choices=[
|
||||
('active', '有效'),
|
||||
('deleted', '已删除')
|
||||
],
|
||||
verbose_name='状态'
|
||||
)
|
||||
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
|
||||
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
|
||||
|
||||
class Meta:
|
||||
db_table = 'knowledge_base_documents'
|
||||
unique_together = ['knowledge_base', 'document_id']
|
||||
indexes = [
|
||||
models.Index(fields=['knowledge_base', 'status']),
|
||||
models.Index(fields=['document_id']),
|
||||
models.Index(fields=['external_id'])
|
||||
]
|
||||
verbose_name = '知识库文档'
|
||||
verbose_name_plural = '知识库文档'
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.knowledge_base.name} - {self.document_name}"
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user