改了过滤

This commit is contained in:
jlj 2025-05-20 10:36:39 +08:00
parent 534c9f6677
commit efafe4c452
2 changed files with 38 additions and 753 deletions

View File

@ -12,6 +12,7 @@ import shutil
import dotenv
import random
import uuid
from django.db.models import Q
dotenv.load_dotenv()
@ -24,729 +25,6 @@ directory_monitoring = {}
monitor_thread = None
is_monitoring = False
# # 在文件开头定义日志目录
# BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# LOG_DIR = os.path.join(BASE_DIR, 'logs', 'process_monitor')
# 创建保存视频的基本路径
# TIKTOK_VIDEOS_PATH = os.path.join(BASE_DIR, 'media', 'tiktok_videos')
# 确保基本目录存在
# os.makedirs(TIKTOK_VIDEOS_PATH, exist_ok=True)
# 确保基础目录结构存在,添加 'all' 目录
# for resource_type in ['cpu', 'memory', 'gpu', 'all']:
# os.makedirs(os.path.join(LOG_DIR, resource_type), exist_ok=True)
# 全局变量来跟踪监控的目录
# monitored_directories = set()
# 在文件顶部添加 API 基础 URL
# API_BASE_URL = os.getenv("API_BASE_URL")
#
# @csrf_exempt
# @require_http_methods(["POST"])
# def fetch_tiktok_videos(request):
# """获取TikTok视频"""
# try:
# # 添加全局变量引用
# global all_downloaded_videos
#
# # 如果变量未初始化,则初始化为空列表
# if 'all_downloaded_videos' not in globals():
# all_downloaded_videos = []
#
# data = json.loads(request.body)
# unique_id = data.get('unique_id')
#
# if not unique_id:
# return JsonResponse({
# 'status': 'error',
# 'message': '请提供TikTok用户ID(unique_id)'
# }, json_dumps_params={'ensure_ascii': False})
#
# # 检查数据库中是否已存在该unique_id
# if TiktokUserVideos.objects.filter(unique_id=unique_id).exists():
# logger.info(f"用户 {unique_id} 已存在于数据库中,跳过处理")
# return JsonResponse({
# 'status': 'success',
# 'message': f'用户 {unique_id} 已存在,跳过处理'
# }, json_dumps_params={'ensure_ascii': False})
#
# # 获取creator_oec_id
# creator_oec_id = data.get('creator_oec_id')
# logger.info(f"从请求数据中获取到creator_oec_id: {creator_oec_id}")
#
# # 调用API获取用户资料和secUid
# logger.info(f"正在获取用户 {unique_id} 的资料...")
# # user_profile = fetch_user_profile(unique_id)
# user_profile = None
# if not user_profile or 'data' not in user_profile:
# # 尝试使用备用方法获取用户资料
# logger.info(f"尝试使用备用方法获取用户 {unique_id} 的资料...")
#
# # 从data中获取creator_oec_id
# try:
# # 从响应中提取creator_oec_id
# creator_oec_id = data.get('creator_oec_id')
# logger.info(f"从请求数据中获取到creator_oec_id: {creator_oec_id}")
#
# # 如果有creator_oec_id则使用备用方法获取用户资料
# if creator_oec_id:
# user_profile = fetch_user_profile_1(creator_oec_id)
#
# if not user_profile or 'data' not in user_profile:
# return JsonResponse({
# 'status': 'error',
# 'message': f'无法获取用户 {unique_id} 的资料(两种方法均失败)'
# }, json_dumps_params={'ensure_ascii': False})
# else:
# return JsonResponse({
# 'status': 'error',
# 'message': f'无法获取用户 {unique_id} 的资料'
# }, json_dumps_params={'ensure_ascii': False})
# except Exception as e:
# logger.error(f"备用方法获取用户资料失败: {e}")
# return JsonResponse({
# 'status': 'error',
# 'message': f'无法获取用户 {unique_id} 的资料: {str(e)}'
# }, json_dumps_params={'ensure_ascii': False})
#
# # 从API响应中提取secUid和其他用户信息
# try:
# user_info = user_profile['data']['userInfo']['user']
# sec_uid = user_info['secUid']
#
# # 提取其他用户信息
# nickname = user_info.get('nickname', f'用户_{unique_id}')
# signature = user_info.get('signature', '')
# avatar_url = user_info.get('avatarLarger', '')
# user_stats = user_profile['data']['userInfo']['stats']
# follower_count = user_stats.get('followerCount', 0)
# heart_count = user_stats.get('heartCount', 0)
#
# logger.info(f"成功获取用户secUid: {sec_uid}")
# except (KeyError, TypeError) as e:
# logger.error(f"解析用户资料出错: {e}")
# return JsonResponse({
# 'status': 'error',
# 'message': f'解析用户资料出错: {str(e)}'
# }, json_dumps_params={'ensure_ascii': False})
#
# # 确保用户目录存在
# user_dir = os.path.join(TIKTOK_VIDEOS_PATH, unique_id)
# os.makedirs(user_dir, exist_ok=True)
#
# # 获取用户视频
# downloaded_videos = []
# videos_data = fetch_user_videos(sec_uid)
# if videos_data and 'data' in videos_data and 'itemList' in videos_data['data']:
# videos = videos_data['data']['itemList']
# user_dir = os.path.join(TIKTOK_VIDEOS_PATH, unique_id)
# os.makedirs(user_dir, exist_ok=True)
#
# # 获取前10个热门视频
# top_videos = sorted(videos, key=lambda x: x.get('stats', {}).get('playCount', 0), reverse=True)[:10]
#
# # 定义下载任务函数
# def download_task(video):
# try:
# video_id = video.get('id', '')
# if not video_id:
# return None
#
# save_path = os.path.join(user_dir, f"{video_id}.mp4")
#
# stats = video.get('stats', {})
# play_count = int(stats.get('playCount', 0))
#
# # 检查是否已下载过该视频
# is_downloaded = os.path.exists(save_path) and os.path.getsize(save_path) > 0
#
# if is_downloaded and is_valid_video_file(save_path):
# logger.info(f"视频已存在且有效,跳过下载: {video_id}")
# # 即使跳过下载,也添加到已下载列表中
# return {
# 'id': video_id,
# 'desc': video.get('desc', ''),
# 'play_count': play_count,
# 'user_unique_id': unique_id,
# 'skipped': True
# }
# elif download_video(video_id, unique_id, save_path):
# # download_video函数内部已经检查了文件有效性
# return {
# 'id': video_id,
# 'desc': video.get('desc', ''),
# 'play_count': play_count,
# 'user_unique_id': unique_id,
# 'skipped': False
# }
# return None
# except Exception as e:
# logger.error(f"下载视频时出错: {e}")
# return None
#
# # 使用线程池并发下载
# with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
# # 提交所有下载任务
# future_to_video = {executor.submit(download_task, video): video for video in top_videos}
#
# # 获取结果
# for future in concurrent.futures.as_completed(future_to_video):
# result = future.result()
# if result:
# downloaded_videos.append(result)
#
# all_downloaded_videos.extend(downloaded_videos)
#
# # 视频下载完成后先调用API分析视频然后再保存到数据库
# if downloaded_videos: # 只有当有视频下载成功时才处理
# video_info_json = json.dumps([{
# 'id': v['id'],
# 'desc': v['desc'],
# 'play_count': v['play_count']
# } for v in downloaded_videos], ensure_ascii=False)
#
# # 先调用视频分析和文档创建API
# document_id = analyze_videos_and_create_document(user_dir, nickname, unique_id, sec_uid)
#
# # 只有在API调用成功后才写入数据库
# if document_id:
# user_record = TiktokUserVideos.objects.update_or_create(
# sec_user_id=sec_uid,
# defaults={
# 'unique_id': unique_id, # 添加unique_id字段
# 'nickname': nickname,
# 'signature': signature,
# 'follower_count': follower_count,
# 'total_favorited': heart_count,
# 'avatar_url': avatar_url,
# 'videos_folder': user_dir,
# 'video_paths': video_info_json,
# 'creator_oec_id': creator_oec_id,
# 'document_id': document_id
# }
# )
# logger.info(
# f"API调用成功用户 {nickname} 的数据已写入数据库,下载视频数: {len(downloaded_videos)}document_id: {document_id}")
# else:
# logger.warning(f"API调用失败跳过用户 {nickname} 的数据库写入")
# else:
# logger.warning(f"未获取到用户 {unique_id} 的视频数据")
# document_id = None
#
# return JsonResponse({
# 'status': 'success',
# 'message': '处理完成'
# }, json_dumps_params={'ensure_ascii': False})
#
# except Exception as e:
# logger.error(f"处理TikTok视频失败: {e}")
# import traceback
# logger.error(f"详细错误: {traceback.format_exc()}")
# return JsonResponse({
# 'status': 'error',
# 'message': f'处理TikTok视频失败: {str(e)}'
# }, json_dumps_params={'ensure_ascii': False})
#
#
# @require_http_methods(["GET"])
# def get_tiktok_user_videos(request):
# """获取已下载的TikTok用户视频列表"""
# try:
# sec_user_id = request.GET.get('sec_user_id')
#
# if not sec_user_id:
# # 如果没有指定用户ID返回所有用户列表
# users = TiktokUserVideos.objects.all().values('sec_user_id', 'unique_id', 'nickname', 'follower_count',
# 'videos_folder', 'create_time', 'avatar_url', 'signature',
# 'creator_oec_id')
# return JsonResponse({
# 'status': 'success',
# 'users': list(users)
# }, json_dumps_params={'ensure_ascii': False})
#
# # 查询指定用户信息
# try:
# user = TiktokUserVideos.objects.get(sec_user_id=sec_user_id)
# # 解析视频信息JSON
# video_info = json.loads(user.video_paths) if user.video_paths else []
#
# # 获取文件夹中的文件列表
# videos_folder = user.videos_folder
# video_files = []
# if os.path.exists(videos_folder):
# video_files = [f for f in os.listdir(videos_folder) if os.path.isfile(os.path.join(videos_folder, f))]
#
# except TiktokUserVideos.DoesNotExist:
# return JsonResponse({
# 'status': 'error',
# 'message': f'用户 {sec_user_id} 不存在'
# }, json_dumps_params={'ensure_ascii': False})
#
# return JsonResponse({
# 'status': 'success',
# 'user_info': {
# 'sec_user_id': user.sec_user_id,
# 'unique_id': user.unique_id,
# 'nickname': user.nickname,
# 'signature': user.signature,
# 'follower_count': user.follower_count,
# 'total_favorited': user.total_favorited,
# 'avatar_url': user.avatar_url,
# 'creator_oec_id': user.creator_oec_id, # 添加creator_oec_id字段
# 'create_time': user.create_time.strftime('%Y-%m-%d %H:%M:%S'),
# 'update_time': user.update_time.strftime('%Y-%m-%d %H:%M:%S')
# },
# 'videos_folder': videos_folder,
# 'video_files': video_files,
# 'video_info': video_info
# }, json_dumps_params={'ensure_ascii': False})
#
# except Exception as e:
# logger.error(f"获取TikTok视频列表失败: {str(e)}")
# return JsonResponse({
# 'status': 'error',
# 'message': f'获取TikTok视频列表失败: {str(e)}'
# }, json_dumps_params={'ensure_ascii': False})
#
#
# # 辅助函数
#
# def fetch_user_videos(sec_uid, cursor=0, count=30):
# """获取用户视频列表"""
# url = f"{API_BASE_URL}/api/tiktok/web/fetch_user_post?secUid={sec_uid}&cursor={cursor}&count={count}"
#
# try:
# response = requests.get(url, timeout=30)
#
# if response.status_code == 200:
# data = response.json()
# logger.info(f"成功获取用户视频,共 {len(data['data'].get('itemList', []))} 个视频")
# return data
# else:
# logger.error(f"获取用户视频失败: {response.status_code}")
# return None
# except Exception as e:
# logger.error(f"获取用户视频异常: {e}")
# return None
#
#
# def fetch_user_profile(unique_id):
# """获取用户基本信息"""
# url = f"{API_BASE_URL}/api/tiktok/web/fetch_user_profile?uniqueId={unique_id}"
#
# try:
# logger.info(f"正在请求用户资料: {url}")
# response = requests.get(url, timeout=30)
#
# if response.status_code == 200:
# data = response.json()
# logger.info(f"成功获取用户资料: {unique_id}")
#
# # 打印完整响应以便调试
# logger.info(f"API原始响应: {data}")
#
# # 验证数据完整性
# if 'data' not in data or not data['data']:
# logger.error(f"API响应缺少data字段: {data}")
# return None
#
# if 'userInfo' not in data['data'] or not data['data']['userInfo']:
# logger.error(f"API响应缺少userInfo字段: {data['data']}")
# return None
#
# if 'user' not in data['data']['userInfo'] or not data['data']['userInfo']['user']:
# logger.error(f"API响应缺少user字段: {data['data']['userInfo']}")
# return None
#
# # 打印用户信息
# logger.info(f"用户信息: {data['data']['userInfo']['user']}")
#
# return data
# else:
# logger.error(f"获取用户信息失败: HTTP {response.status_code}, 响应: {response.text[:500]}")
# return None
# except Exception as e:
# logger.error(f"获取用户信息异常: {e}")
# return None
#
#
# def get_sec_user_id(unique_id):
# """
# 通过TikTok用户名获取secUid
#
# Args:
# unique_id: TikTok用户名
#
# Returns:
# secUid字符串如果获取失败则返回None
# """
# url = f"{API_BASE_URL}/api/tiktok/web/get_sec_user_id?url=https://www.tiktok.com/@{unique_id}"
#
# try:
# logger.info(f"正在请求secUid: {url}")
# response = requests.get(url, timeout=30)
#
# if response.status_code == 200:
# data = response.json()
# logger.info(f"成功获取secUid: {data}")
#
# if 'data' in data and data['data']:
# sec_uid = data['data']
# logger.info(f"获取到secUid: {sec_uid}")
# return sec_uid
# else:
# logger.error(f"API响应缺少data字段或data为空: {data}")
# return None
# else:
# logger.error(f"获取secUid失败: HTTP {response.status_code}, 响应: {response.text[:500]}")
# return None
# except Exception as e:
# logger.error(f"获取secUid异常: {e}")
# return None
#
#
# def fetch_user_profile_1(creator_oec_id):
# """
# 通过creator_oec_id获取用户基本信息
#
# 当fetch_user_profile无法获取用户信息时使用此备用方法
# 通过POST请求获取用户详细资料
#
# Args:
# creator_oec_id: 创作者OEC ID
#
# Returns:
# 与fetch_user_profile相同格式的用户信息
# """
# url = "http://100.65.206.105:8899/profile"
#
# try:
# logger.info(f"正在通过creator_oec_id请求用户资料: {creator_oec_id}")
#
# # 构建请求体
# payload = {
# "creator_oec_id": creator_oec_id,
# "profile_types": [1, 6]
# }
#
# # 发送POST请求
# response = requests.post(url, json=payload, timeout=30)
#
# if response.status_code == 200:
# data = response.json()
# logger.info(f"成功获取用户资料(方法2): {creator_oec_id}")
#
# # 验证数据完整性
# if 'creator_profile' not in data:
# logger.error(f"API响应缺少creator_profile字段: {data}")
# return None
#
# # 转换为与fetch_user_profile相同的格式
# creator_profile = data.get('creator_profile', {})
#
# # 获取uniqueId
# unique_id = creator_profile.get('handle', {}).get('value', '')
#
# # 通过uniqueId获取secUid
# sec_uid = None
# if unique_id:
# sec_uid = get_sec_user_id(unique_id)
#
# # 如果无法获取secUid使用一个占位符
# if not sec_uid:
# logger.warning(f"无法获取用户 {unique_id} 的secUid使用占位符")
# sec_uid = f"placeholder_secuid_{creator_oec_id}"
#
# # 构建与原API相同格式的响应
# formatted_data = {
# 'data': {
# 'userInfo': {
# 'user': {
# 'secUid': sec_uid,
# 'uniqueId': unique_id,
# 'nickname': creator_profile.get('nickname', {}).get('value', ''),
# 'signature': creator_profile.get('bio', {}).get('value', ''),
# 'avatarLarger': creator_profile.get('avatar', {}).get('value', {}).get('url_list', [''])[0]
# },
# 'stats': {
# 'followerCount': int(creator_profile.get('follower_cnt', {}).get('value', '0')),
# 'heartCount': 0, # 没有对应字段设为0
# 'followingCount': 0, # 没有对应字段设为0
# 'videoCount': 0 # 没有对应字段设为0
# }
# }
# }
# }
#
# return formatted_data
# else:
# logger.error(f"获取用户信息失败(方法2): HTTP {response.status_code}, 响应: {response.text[:500]}")
# return None
# except Exception as e:
# logger.error(f"获取用户信息异常(方法2): {e}")
# import traceback
# logger.error(f"详细错误: {traceback.format_exc()}")
# return None
#
#
# def is_valid_video_file(file_path):
# """
# 检查视频文件是否有效
#
# Args:
# file_path: 视频文件路径
#
# Returns:
# bool: 如果文件有效返回True否则返回False
# """
# try:
# # 检查文件是否存在
# if not os.path.exists(file_path):
# logger.error(f"视频文件不存在: {file_path}")
# return False
#
# # 检查文件大小是否合理 (大于10KB)
# file_size = os.path.getsize(file_path)
# if file_size < 10 * 1024: # 小于10KB的文件可能是无效的
# logger.warning(f"视频文件过小,可能无效: {file_path},大小: {file_size}字节")
# return False
#
# # 检查文件是否可读
# with open(file_path, 'rb') as f:
# # 尝试读取前100字节
# data = f.read(100)
# if not data:
# logger.warning(f"视频文件内容为空: {file_path}")
# return False
#
# return True
#
# except Exception as e:
# logger.error(f"验证视频文件时出错: {e}")
# return False
#
#
# def download_video(video_id, unique_id, save_path):
# """使用API的直接下载接口下载TikTok视频"""
# # 确保视频ID是纯数字
# if not str(video_id).isdigit():
# logger.error(f"无效的视频ID: {video_id},必须是纯数字")
# return False
#
# # 检查文件是否已存在
# if os.path.exists(save_path):
# file_size = os.path.getsize(save_path)
# if file_size > 0: # 确保文件不是空文件
# # 进一步验证文件有效性
# if is_valid_video_file(save_path):
# logger.info(f"视频文件已存在且有效,跳过下载: {save_path},文件大小: {file_size}字节")
# return True
# else:
# logger.warning(f"发现无效视频文件,将重新下载: {save_path}")
# # 删除无效文件
# os.remove(save_path)
# else:
# logger.warning(f"发现空视频文件,将重新下载: {save_path}")
# # 删除空文件
# os.remove(save_path)
#
# # 构建标准TikTok视频URL
# tiktok_url = f"https://www.tiktok.com/@{unique_id}/video/{video_id}"
# logger.info(f"构建的TikTok URL: {tiktok_url}")
#
# # 构建完整的API请求URL
# api_url = f"{API_BASE_URL}/api/download"
# full_url = f"{api_url}?url={tiktok_url}&prefix=true&with_watermark=false"
# logger.info(f"完整的API请求URL: {full_url}")
#
# try:
# # 直接使用完整URL发送请求
# response = requests.get(full_url, stream=True, timeout=60)
#
# # 检查响应状态
# if response.status_code != 200:
# logger.error(
# f"下载视频失败: {response.status_code} - {response.text[:200] if response.text else '无响应内容'}")
# return False
#
# # 获取内容类型
# content_type = response.headers.get('Content-Type', '')
# logger.info(f"响应内容类型: {content_type}")
#
# # 保存文件
# with open(save_path, 'wb') as f:
# for chunk in response.iter_content(chunk_size=8192):
# if chunk:
# f.write(chunk)
#
# file_size = os.path.getsize(save_path)
# logger.info(f"视频已下载到: {save_path},文件大小: {file_size}字节")
#
# # 验证下载的文件是否有效
# if is_valid_video_file(save_path):
# logger.info(f"视频文件验证通过: {save_path}")
# return True
# else:
# logger.error(f"下载的视频文件无效: {save_path}")
# # 删除无效文件
# if os.path.exists(save_path):
# os.remove(save_path)
# return False
#
# except Exception as e:
# logger.error(f"下载视频异常: {e}")
# import traceback
# logger.error(f"详细错误: {traceback.format_exc()}")
# return False
#
#
# def analyze_videos_and_create_document(videos_folder, nickname, unique_id, sec_uid):
# """
# 分析视频目录并创建Yanxi文档
#
# Args:
# videos_folder: 视频所在目录路径
# nickname: 用户昵称
# unique_id: TikTok用户ID
# sec_uid: 用户的安全ID
#
# Returns:
# str: 如果API调用成功返回document_id否则返回None
# """
# try:
# # 直接调用analyze_directory函数进行视频分析
# from app.api.summary.summary import analyze_directory
#
# logger.info(f"开始分析视频目录: {videos_folder}")
# analyze_result = analyze_directory(videos_folder)
#
# if analyze_result:
# logger.info(f"分析成功")
#
# # 提取分析结果中的用户画像和聚合摘要
# user_persona = analyze_result.get('user_persona', '')
# content_summary = analyze_result.get('content_summary', '')
#
# content = f"{user_persona}\n\n{content_summary}"
#
# # 调用yanxi API创建文档
# try:
# yanxi_url = "http://localhost:8899/yanxi/api/dataset/231aaa42-fc97-11ef-a8ef-0242ac120006/document"
# yanxi_data = {
# "name": f"{nickname}@{unique_id}",
# "paragraphs": [
# {
# "content": content,
# "title": sec_uid,
# "is_active": True
# }
# ]
# }
#
# logger.info(f"调用Yanxi API: {yanxi_url}")
# yanxi_response = requests.post(
# yanxi_url,
# json=yanxi_data,
# headers={"Content-Type": "application/json"},
# timeout=60
# )
#
# if yanxi_response.status_code in [200, 201]:
# response_data = yanxi_response.json()
# document_id = response_data.get('data', {}).get('id')
# if document_id:
# logger.info(f"文档创建成功document_id: {document_id}")
# return document_id
# else:
# logger.error("文档创建成功但未获取到document_id")
# return None
# else:
# logger.error(f"文档创建失败: {yanxi_response.status_code}, {yanxi_response.text}")
# return None
# except Exception as e:
# logger.error(f"调用Yanxi API出错: {e}")
# return None
# else:
# logger.error(f"分析失败")
# return None
# except Exception as e:
# logger.error(f"视频分析出错: {e}")
# return None
#
#
# @csrf_exempt
# @require_http_methods(["DELETE"])
# def delete_tiktok_user(request):
# """删除TikTok用户及其相关视频和文档"""
# try:
# data = json.loads(request.body)
# sec_uid = data.get('sec_uid')
#
# if not sec_uid:
# return JsonResponse({
# 'status': 'error',
# 'message': 'invalid params'
# }, json_dumps_params={'ensure_ascii': False})
#
# try:
# user = TiktokUserVideos.objects.get(sec_user_id=sec_uid)
# except TiktokUserVideos.DoesNotExist:
# return JsonResponse({
# 'status': 'error',
# 'message': f'用户 {sec_uid} 不存在'
# }, json_dumps_params={'ensure_ascii': False})
#
# # 获取必要信息
# videos_folder = user.videos_folder
# document_id = user.document_id
#
# # 1. 删除视频文件夹
# if videos_folder and os.path.exists(videos_folder):
# try:
# shutil.rmtree(videos_folder)
# logger.info(f"成功删除视频文件夹: {videos_folder}")
# except Exception as e:
# logger.error(f"删除视频文件夹失败: {e}")
#
# # 2. 删除文档
# if document_id:
# try:
# delete_url = f"http://localhost:8899/yanxi/api/dataset/231aaa42-fc97-11ef-a8ef-0242ac120006/document/{document_id}"
# delete_response = requests.delete(
# delete_url,
# headers={"Content-Type": "application/json"},
# timeout=30
# )
#
# if delete_response.status_code in [200, 204]:
# logger.info(f"成功删除文档: {document_id}")
# else:
# logger.error(f"删除文档失败: {delete_response.status_code}, {delete_response.text}")
# except Exception as e:
# logger.error(f"调用删除文档API出错: {e}")
#
# # 3. 删除数据库记录
# user.delete()
# logger.info(f"成功删除用户数据: {sec_uid}")
#
# return JsonResponse({
# 'status': 'success',
# 'message': f'成功删除用户 {sec_uid} 及其相关数据'
# }, json_dumps_params={'ensure_ascii': False})
#
# except Exception as e:
# logger.error(f"删除用户异常: {e}")
# import traceback
# logger.error(f"详细错误: {traceback.format_exc()}")
# return JsonResponse({
# 'status': 'error',
# 'message': f'删除用户时发生错误: {str(e)}'
# }, json_dumps_params={'ensure_ascii': False})
@csrf_exempt
@require_http_methods(["POST"])
@ -765,29 +43,32 @@ def filter_creators(request):
# 基础查询
query = CreatorProfile.objects.all()
# Category 选过滤
# Category 选过滤
category = filter_data.get('category')
if category and len(category) > 0:
query = query.filter(category=category[0])
query = query.filter(category__in=category)
# 电商能力等级过滤 (L1-L7)
# 电商能力等级过滤 (L1-L7)
e_commerce_level = filter_data.get('e_commerce_level')
if e_commerce_level and len(e_commerce_level) > 0:
level_str = e_commerce_level[0]
level_nums = []
for level_str in e_commerce_level:
if level_str.startswith('L'):
level_num = int(level_str[1:])
query = query.filter(e_commerce_level=level_num)
level_nums.append(int(level_str[1:]))
if level_nums:
query = query.filter(e_commerce_level__in=level_nums)
# 曝光等级过滤 (KOL-1, KOL-2, KOC-1等)
# 曝光等级过滤 (KOL-1, KOL-2, KOC-1等)
exposure_level = filter_data.get('exposure_level')
if exposure_level and len(exposure_level) > 0:
query = query.filter(exposure_level=exposure_level[0])
query = query.filter(exposure_level__in=exposure_level)
# GMV范围过滤 ($0-$5k, $5k-$25k, $25k-$50k等)
# GMV范围过滤 ($0-$5k, $5k-$25k, $25k-$50k等)
gmv_range = filter_data.get('gmv_range')
if gmv_range and len(gmv_range) > 0:
gmv_q = Q()
for gmv_val in gmv_range:
gmv_min, gmv_max = 0, float('inf')
gmv_val = gmv_range[0]
if gmv_val == "$0-$5k":
gmv_min, gmv_max = 0, 5
elif gmv_val == "$5k-$25k":
@ -801,12 +82,16 @@ def filter_creators(request):
elif gmv_val == "$400k-$1500k":
gmv_min, gmv_max = 400, 1500
elif gmv_val == "$1500k+":
gmv_min = 1500
gmv_min, gmv_max = 1500, float('inf')
range_q = Q()
if gmv_min > 0:
query = query.filter(gmv__gte=gmv_min)
range_q &= Q(gmv__gte=gmv_min)
if gmv_max < float('inf'):
query = query.filter(gmv__lte=gmv_max)
range_q &= Q(gmv__lte=gmv_max)
gmv_q |= range_q
query = query.filter(gmv_q)
# 观看量范围过滤,单选
views_range = filter_data.get('views_range')

BIN
requirements.txt Normal file

Binary file not shown.