From 32d09a9ac7ebaaad132c8a26fcd1218fb4e8dfc4 Mon Sep 17 00:00:00 2001 From: jlj <3042504846@qq.com> Date: Fri, 6 Jun 2025 15:15:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/daren_detail/views.py | 224 ++++++++++++++++++++++++++++--------- test_avatar_display.py | 117 ------------------- 2 files changed, 174 insertions(+), 167 deletions(-) delete mode 100644 test_avatar_display.py diff --git a/apps/daren_detail/views.py b/apps/daren_detail/views.py index e0a3c99..81c361a 100644 --- a/apps/daren_detail/views.py +++ b/apps/daren_detail/views.py @@ -3300,10 +3300,32 @@ def filter_private_pool_creators(request): 'message': f'找不到ID为 {pool_id} 的私有库', 'data': None }, json_dumps_params={'ensure_ascii': False}) + else: + # 当不提供pool_id时,需要去除重复的达人 + # 使用distinct('creator')获取不重复的达人关系 + # 由于Django ORM的限制,我们需要在内存中进行去重 + seen_creator_ids = set() + unique_relations = [] + + # 先获取所有符合条件的关系 + all_relations = list(creator_relations) + + # 在内存中去重,只保留每个creator_id的第一条记录 + for relation in all_relations: + if relation.creator.id not in seen_creator_ids: + seen_creator_ids.add(relation.creator.id) + unique_relations.append(relation) + + # 使用去重后的关系列表 + creator_relations = unique_relations # 应用状态过滤条件(仅当提供了status参数时) if status: - creator_relations = creator_relations.filter(status=status) + if pool_id: + creator_relations = creator_relations.filter(status=status) + else: + # 在内存中进行过滤 + creator_relations = [relation for relation in creator_relations if relation.status == status] # 应用复杂过滤条件 # --------- 从filter_creators借鉴的过滤逻辑 --------- @@ -3311,7 +3333,12 @@ def filter_private_pool_creators(request): # Category 多选过滤 category = filter_data.get('category') if category and len(category) > 0: - creator_relations = creator_relations.filter(creator__category__in=category) + if pool_id: + creator_relations = creator_relations.filter(creator__category__in=category) + else: + # 在内存中过滤 + creator_relations = [relation for relation in creator_relations + if relation.creator.category in category] # 电商能力等级过滤 (L1-L7),多选 e_commerce_level = filter_data.get('e_commerce_level') @@ -3321,47 +3348,89 @@ def filter_private_pool_creators(request): if level_str.startswith('L'): level_nums.append(int(level_str[1:])) if level_nums: - creator_relations = creator_relations.filter(creator__e_commerce_level__in=level_nums) + if pool_id: + creator_relations = creator_relations.filter(creator__e_commerce_level__in=level_nums) + else: + # 在内存中过滤 + creator_relations = [relation for relation in creator_relations + if relation.creator.e_commerce_level in level_nums] # 曝光等级过滤 (KOL-1, KOL-2, KOC-1等),多选 exposure_level = filter_data.get('exposure_level') if exposure_level and len(exposure_level) > 0: - creator_relations = creator_relations.filter(creator__exposure_level__in=exposure_level) + if pool_id: + creator_relations = creator_relations.filter(creator__exposure_level__in=exposure_level) + else: + # 在内存中过滤 + creator_relations = [relation for relation in creator_relations + if relation.creator.exposure_level in exposure_level] # 平台过滤(tiktok, instagram, youtube等),单选 platform = filter_data.get('platform') if platform and platform: - creator_relations = creator_relations.filter(creator__profile=platform) + if pool_id: + creator_relations = creator_relations.filter(creator__profile=platform) + else: + # 在内存中过滤 + creator_relations = [relation for relation in creator_relations + if relation.creator.profile == platform] # 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') - if gmv_val == "$0-$5k": - gmv_min, gmv_max = 0, 5 - elif gmv_val == "$5k-$25k": - gmv_min, gmv_max = 5, 25 - elif gmv_val == "$25k-$50k": - gmv_min, gmv_max = 25, 50 - elif gmv_val == "$50k-$150k": - gmv_min, gmv_max = 50, 150 - elif gmv_val == "$150k-$400k": - gmv_min, gmv_max = 150, 400 - elif gmv_val == "$400k-$1500k": - gmv_min, gmv_max = 400, 1500 - elif gmv_val == "$1500k+": - gmv_min, gmv_max = 1500, float('inf') + if pool_id: + gmv_q = Q() + for gmv_val in gmv_range: + gmv_min, gmv_max = 0, float('inf') + if gmv_val == "$0-$5k": + gmv_min, gmv_max = 0, 5 + elif gmv_val == "$5k-$25k": + gmv_min, gmv_max = 5, 25 + elif gmv_val == "$25k-$50k": + gmv_min, gmv_max = 25, 50 + elif gmv_val == "$50k-$150k": + gmv_min, gmv_max = 50, 150 + elif gmv_val == "$150k-$400k": + gmv_min, gmv_max = 150, 400 + elif gmv_val == "$400k-$1500k": + gmv_min, gmv_max = 400, 1500 + elif gmv_val == "$1500k+": + gmv_min, gmv_max = 1500, float('inf') - range_q = Q() - if gmv_min > 0: - range_q &= Q(creator__gmv__gte=gmv_min) - if gmv_max < float('inf'): - range_q &= Q(creator__gmv__lte=gmv_max) - gmv_q |= range_q + range_q = Q() + if gmv_min > 0: + range_q &= Q(creator__gmv__gte=gmv_min) + if gmv_max < float('inf'): + range_q &= Q(creator__gmv__lte=gmv_max) + gmv_q |= range_q - creator_relations = creator_relations.filter(gmv_q) + creator_relations = creator_relations.filter(gmv_q) + else: + # 在内存中过滤 + filtered_relations = [] + for relation in creator_relations: + creator_gmv = relation.creator.gmv or 0 + for gmv_val in gmv_range: + gmv_min, gmv_max = 0, float('inf') + if gmv_val == "$0-$5k": + gmv_min, gmv_max = 0, 5 + elif gmv_val == "$5k-$25k": + gmv_min, gmv_max = 5, 25 + elif gmv_val == "$25k-$50k": + gmv_min, gmv_max = 25, 50 + elif gmv_val == "$50k-$150k": + gmv_min, gmv_max = 50, 150 + elif gmv_val == "$150k-$400k": + gmv_min, gmv_max = 150, 400 + elif gmv_val == "$400k-$1500k": + gmv_min, gmv_max = 400, 1500 + elif gmv_val == "$1500k+": + gmv_min, gmv_max = 1500, float('inf') + + if gmv_min <= creator_gmv <= gmv_max: + filtered_relations.append(relation) + break + creator_relations = filtered_relations # 观看量范围过滤,使用数值数组格式 views_range = filter_data.get('views_range') @@ -3369,10 +3438,19 @@ def filter_private_pool_creators(request): views_min = views_range[0] views_max = views_range[1] - if views_min is not None: - creator_relations = creator_relations.filter(creator__avg_video_views__gte=views_min) - if views_max is not None: - creator_relations = creator_relations.filter(creator__avg_video_views__lte=views_max) + if pool_id: + if views_min is not None: + creator_relations = creator_relations.filter(creator__avg_video_views__gte=views_min) + if views_max is not None: + creator_relations = creator_relations.filter(creator__avg_video_views__lte=views_max) + else: + # 在内存中过滤 + filtered_relations = [] + for relation in creator_relations: + views = relation.creator.avg_video_views or 0 + if (views_min is None or views >= views_min) and (views_max is None or views <= views_max): + filtered_relations.append(relation) + creator_relations = filtered_relations # 价格区间过滤逻辑,使用数值数组格式 pricing = filter_data.get('pricing') @@ -3380,20 +3458,32 @@ def filter_private_pool_creators(request): min_price = pricing[0] max_price = pricing[1] - if min_price is not None: - creator_relations = creator_relations.filter(creator__pricing__gte=min_price) - if max_price is not None: - creator_relations = creator_relations.filter(creator__pricing__lte=max_price) + if pool_id: + if min_price is not None: + creator_relations = creator_relations.filter(creator__pricing__gte=min_price) + if max_price is not None: + creator_relations = creator_relations.filter(creator__pricing__lte=max_price) + else: + # 在内存中过滤 + filtered_relations = [] + for relation in creator_relations: + price = relation.creator.pricing or 0 + if (min_price is None or price >= min_price) and (max_price is None or price <= max_price): + filtered_relations.append(relation) + creator_relations = filtered_relations # 获取总数据量 - total_count = creator_relations.count() + total_count = len(creator_relations) if not pool_id else creator_relations.count() # 计算分页 start = (page - 1) * page_size end = start + page_size # 执行查询并分页 - paged_relations = creator_relations[start:end] + if pool_id: + paged_relations = creator_relations[start:end] + else: + paged_relations = creator_relations[start:end] creator_list = [] for relation in paged_relations: @@ -3784,11 +3874,18 @@ def search_private_creators(request): search_mode = request.GET.get('mode', 'and').lower() # 搜索模式:and 或 or,默认为 and page = int(request.GET.get('page', 1)) page_size = int(request.GET.get('page_size', 10)) + + # 获取pool_id参数,如果提供了则只搜索特定库 + pool_id = request.GET.get('pool_id') # 直接搜索用户所有私有库中的达人 query = PrivateCreatorRelation.objects.filter( private_pool__user=user ).select_related('creator', 'private_pool') + + # 如果提供了pool_id,则只搜索特定私有库 + if pool_id: + query = query.filter(private_pool_id=pool_id) # 如果有搜索关键词,进行模糊搜索 if search_query: @@ -3877,16 +3974,42 @@ def search_private_creators(request): else: # 如果没有搜索词,按名称排序 query = query.order_by('creator__name') - - # 获取总数据量 - total_count = query.count() - - # 计算分页 - start = (page - 1) * page_size - end = start + page_size - - # 执行查询并分页 - private_creator_relations = query[start:end] + + # 当不提供pool_id时进行达人去重 + if not pool_id: + # 先获取所有符合条件的关系 + all_relations = list(query) + + # 在内存中去重,只保留每个creator_id的第一条记录 + seen_creator_ids = set() + unique_relations = [] + + for relation in all_relations: + if relation.creator.id not in seen_creator_ids: + seen_creator_ids.add(relation.creator.id) + unique_relations.append(relation) + + # 使用去重后的关系列表 + relations = unique_relations + total_count = len(relations) + + # 计算分页 + start = (page - 1) * page_size + end = min(start + page_size, total_count) + + # 执行分页 + private_creator_relations = relations[start:end] + else: + # 如果提供了pool_id,不需要去重,直接使用数据库查询 + # 获取总数据量 + total_count = query.count() + + # 计算分页 + start = (page - 1) * page_size + end = start + page_size + + # 执行查询并分页 + private_creator_relations = query[start:end] creator_list = [] for relation in private_creator_relations: @@ -3953,7 +4076,8 @@ def search_private_creators(request): "results_count": total_count, "search_applied": bool(search_query), "supports_single_char": True, # 标识支持单字符搜索 - "search_scope": "private_only" # 标识只搜索私有达人库 + "search_scope": "private_only", # 标识只搜索私有达人库 + "is_deduplicated": not pool_id # 标识是否进行了达人去重 } return JsonResponse({ diff --git a/test_avatar_display.py b/test_avatar_display.py deleted file mode 100644 index a9935b1..0000000 --- a/test_avatar_display.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python -""" -测试达人头像显示功能 -演示如何使用本地图片和外部URL -""" - -import os -import django - -# 设置Django环境 -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'daren.settings') -django.setup() - -from apps.daren_detail.models import CreatorProfile -from django.core.files import File -from django.core.files.uploadedfile import SimpleUploadedFile - -def test_avatar_display(): - """测试头像显示功能""" - print("=== 达人头像显示功能测试 ===\n") - - # 1. 查询现有达人 - creators = CreatorProfile.objects.all()[:3] - - print("1. 现有达人头像状态:") - for creator in creators: - avatar_url = creator.get_avatar_url() - has_local = bool(creator.avatar) - has_external = bool(creator.avatar_url) - - print(f" - {creator.name}:") - print(f" 本地图片: {'✓' if has_local else '✗'}") - print(f" 外部URL: {'✓' if has_external else '✗'}") - print(f" 显示URL: {avatar_url or '无'}") - print() - - # 2. 演示URL访问方式 - print("2. 头像URL访问示例:") - for creator in creators: - avatar_url = creator.get_avatar_url() - if avatar_url: - if creator.avatar: - print(f" 本地图片: http://localhost:8000{avatar_url}") - else: - print(f" 外部URL: {avatar_url}") - else: - print(f" {creator.name}: 无头像") - print() - - # 3. 创建测试数据示例 - print("3. 创建测试达人示例:") - - # 示例1:仅外部URL - creator1, created = CreatorProfile.objects.get_or_create( - name="测试达人A", - defaults={ - 'avatar_url': 'https://example.com/avatar1.jpg', - 'category': 'Beauty & Personal Care', - 'followers': 1000 - } - ) - print(f" - {creator1.name}: {creator1.get_avatar_url()}") - - # 示例2:仅本地图片(如果存在的话) - existing_avatar = CreatorProfile.objects.filter(avatar__isnull=False).first() - if existing_avatar: - print(f" - {existing_avatar.name}: {existing_avatar.get_avatar_url()}") - - print("\n=== 前端使用示例代码 ===") - print(""" -// JavaScript: 获取并显示头像 -fetch('/api/daren_detail/creators/') - .then(response => response.json()) - .then(data => { - data.results.forEach(creator => { - if (creator.avatar_display_url) { - console.log(`${creator.name}: ${creator.avatar_display_url}`); - - // 创建图片元素 - const img = document.createElement('img'); - img.src = creator.avatar_display_url; - img.alt = `${creator.name}的头像`; - img.className = 'creator-avatar'; - - // 添加到页面 - document.getElementById('creators-list').appendChild(img); - } - }); - }); -""") - - print("\n=== HTML模板使用示例 ===") - print(""" - -{% for creator in creators %} -