daren/apps/brands/views.py
2025-05-20 16:39:08 +08:00

399 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from django.shortcuts import render, get_object_or_404
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from apps.user.authentication import CustomTokenAuthentication
import logging
from .models import Brand, Product, Campaign, BrandChatSession
from .serializers import (
BrandSerializer,
ProductSerializer,
CampaignSerializer,
BrandChatSessionSerializer,
BrandDetailSerializer
)
from .services.status_polling_service import polling_service
from .services.offer_status_service import OfferStatusService
logger = logging.getLogger(__name__)
def api_response(code=200, message="成功", data=None):
"""统一API响应格式"""
return Response({
'code': code,
'message': message,
'data': data
})
class BrandViewSet(viewsets.ModelViewSet):
"""品牌API视图集"""
queryset = Brand.objects.all()
serializer_class = BrandSerializer
authentication_classes = [CustomTokenAuthentication]
permission_classes = [IsAuthenticated]
def get_serializer_class(self):
if self.action == 'retrieve':
return BrandDetailSerializer
return BrandSerializer
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return api_response(data=serializer.data)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return api_response(data=serializer.data)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
if serializer.is_valid():
self.perform_update(serializer)
return api_response(data=serializer.data)
return api_response(code=400, message="更新失败", data=serializer.errors)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return api_response(message="删除成功", data=None)
@action(detail=True, methods=['get'])
def products(self, request, pk=None):
"""获取品牌下的所有产品"""
brand = self.get_object()
products = Product.objects.filter(brand=brand, is_active=True)
serializer = ProductSerializer(products, many=True)
return api_response(data=serializer.data)
@action(detail=True, methods=['get'])
def campaigns(self, request, pk=None):
"""获取品牌下的所有活动"""
brand = self.get_object()
campaigns = Campaign.objects.filter(brand=brand, is_active=True)
serializer = CampaignSerializer(campaigns, many=True)
return api_response(data=serializer.data)
@action(detail=True, methods=['get'])
def dataset_ids(self, request, pk=None):
"""获取品牌的所有知识库ID"""
brand = self.get_object()
return api_response(data={'dataset_id_list': brand.dataset_id_list})
class ProductViewSet(viewsets.ModelViewSet):
"""产品API视图集"""
queryset = Product.objects.filter(is_active=True)
serializer_class = ProductSerializer
authentication_classes = [CustomTokenAuthentication]
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return api_response(data=serializer.data)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return api_response(data=serializer.data)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
if serializer.is_valid():
self.perform_update(serializer)
return api_response(data=serializer.data)
return api_response(code=400, message="更新失败", data=serializer.errors)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return api_response(message="删除成功", data=None)
def perform_create(self, serializer):
# 创建产品时自动更新品牌的dataset_id_list
product = serializer.save()
brand = product.brand
# 确保dataset_id添加到品牌的dataset_id_list中
if product.dataset_id and product.dataset_id not in brand.dataset_id_list:
brand.dataset_id_list.append(product.dataset_id)
brand.save(update_fields=['dataset_id_list', 'updated_at'])
def perform_update(self, serializer):
# 获取原始产品信息
old_product = self.get_object()
old_dataset_id = old_product.dataset_id
# 保存更新后的产品
product = serializer.save()
brand = product.brand
# 从品牌的dataset_id_list中移除旧的dataset_id添加新的dataset_id
if old_dataset_id in brand.dataset_id_list:
brand.dataset_id_list.remove(old_dataset_id)
if product.dataset_id and product.dataset_id not in brand.dataset_id_list:
brand.dataset_id_list.append(product.dataset_id)
brand.save(update_fields=['dataset_id_list', 'updated_at'])
def perform_destroy(self, instance):
# 软删除产品并从品牌的dataset_id_list中移除对应的ID
instance.is_active = False
instance.save()
brand = instance.brand
if instance.dataset_id in brand.dataset_id_list:
brand.dataset_id_list.remove(instance.dataset_id)
brand.save(update_fields=['dataset_id_list', 'updated_at'])
class CampaignViewSet(viewsets.ModelViewSet):
"""活动API视图集"""
queryset = Campaign.objects.filter(is_active=True)
serializer_class = CampaignSerializer
authentication_classes = [CustomTokenAuthentication]
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return api_response(data=serializer.data)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return api_response(data=serializer.data)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
if serializer.is_valid():
self.perform_update(serializer)
return api_response(data=serializer.data)
return api_response(code=400, message="更新失败", data=serializer.errors)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return api_response(message="删除成功", data=None)
def perform_create(self, serializer):
# 创建活动时自动更新品牌的dataset_id_list
campaign = serializer.save()
brand = campaign.brand
# 确保dataset_id添加到品牌的dataset_id_list中
if campaign.dataset_id and campaign.dataset_id not in brand.dataset_id_list:
brand.dataset_id_list.append(campaign.dataset_id)
brand.save(update_fields=['dataset_id_list', 'updated_at'])
def perform_update(self, serializer):
# 获取原始活动信息
old_campaign = self.get_object()
old_dataset_id = old_campaign.dataset_id
# 保存更新后的活动
campaign = serializer.save()
brand = campaign.brand
# 从品牌的dataset_id_list中移除旧的dataset_id添加新的dataset_id
if old_dataset_id in brand.dataset_id_list:
brand.dataset_id_list.remove(old_dataset_id)
if campaign.dataset_id and campaign.dataset_id not in brand.dataset_id_list:
brand.dataset_id_list.append(campaign.dataset_id)
brand.save(update_fields=['dataset_id_list', 'updated_at'])
def perform_destroy(self, instance):
# 软删除活动并从品牌的dataset_id_list中移除对应的ID
instance.is_active = False
instance.save()
brand = instance.brand
if instance.dataset_id in brand.dataset_id_list:
brand.dataset_id_list.remove(instance.dataset_id)
brand.save(update_fields=['dataset_id_list', 'updated_at'])
@action(detail=True, methods=['post'])
def add_product(self, request, pk=None):
"""将产品添加到活动中"""
campaign = self.get_object()
product_id = request.data.get('product_id')
if not product_id:
return api_response(code=400, message="缺少产品ID", data=None)
try:
product = Product.objects.get(id=product_id, is_active=True)
campaign.link_product.add(product)
return api_response(message="产品添加成功", data=None)
except Product.DoesNotExist:
return api_response(code=404, message="产品不存在", data=None)
except Exception as e:
return api_response(code=500, message=f"添加产品失败: {str(e)}", data=None)
@action(detail=True, methods=['post'])
def remove_product(self, request, pk=None):
"""从活动中移除产品"""
campaign = self.get_object()
product_id = request.data.get('product_id')
if not product_id:
return api_response(code=400, message="缺少产品ID", data=None)
try:
product = Product.objects.get(id=product_id)
campaign.link_product.remove(product)
return api_response(message="产品移除成功", data=None)
except Product.DoesNotExist:
return api_response(code=404, message="产品不存在", data=None)
except Exception as e:
return api_response(code=500, message=f"移除产品失败: {str(e)}", data=None)
@action(detail=True, methods=['get'])
def creator_list(self, request, pk=None):
"""获取活动关联的达人列表"""
campaign = self.get_object()
from apps.daren_detail.models import CreatorCampaign, CreatorProfile
# 获取所有达人数据
creator_list = OfferStatusService.get_campaign_creator_data(campaign.id)
# 启动状态轮询(当有用户请求此接口时)
try:
# 获取产品ID
product_id = None
if campaign.link_product.exists():
product = campaign.link_product.first()
product_id = product.id
# 如果没有关联产品则使用活动ID作为产品ID
if not product_id:
product_id = campaign.id
# 构建达人-产品对
creator_product_pairs = []
for creator_data in creator_list:
creator_id = creator_data['id']
creator_product_pairs.append((creator_id, product_id))
# 启动轮询
if creator_product_pairs:
polling_service.start_polling(
campaign_id=campaign.id,
creator_product_pairs=creator_product_pairs,
interval=30 # 每30秒轮询一次
)
except Exception as e:
logger.error(f"启动状态轮询时出错: {str(e)}")
return api_response(data=creator_list)
@action(detail=True, methods=['post'])
def update_creator_status(self, request, pk=None):
"""手动更新达人状态"""
campaign = self.get_object()
from apps.daren_detail.models import CreatorCampaign
from .services.offer_status_service import OfferStatusService
# 获取传入的达人ID
creator_id = request.data.get('creator_id')
if not creator_id:
return api_response(code=400, message="缺少必要参数: creator_id", data=None)
try:
# 查询达人与活动的关联
creator_campaign = CreatorCampaign.objects.get(
campaign_id=campaign.id,
creator_id=creator_id
)
# 获取产品ID
product_id = None
if campaign.link_product.exists():
product = campaign.link_product.first()
product_id = product.id
# 如果没有关联产品则使用活动ID作为产品ID
if not product_id:
product_id = campaign.id
# 获取最新状态
status = OfferStatusService.fetch_status(creator_id, product_id)
if status:
# 更新状态
creator_campaign.status = status
creator_campaign.save()
# 获取所有达人的最新数据
creator_list = OfferStatusService.get_campaign_creator_data(campaign.id)
# 发送WebSocket更新
OfferStatusService.send_status_update(campaign.id, creator_id, status)
return api_response(message="状态已更新", data=creator_list)
else:
return api_response(code=500, message="获取状态失败", data=None)
except CreatorCampaign.DoesNotExist:
return api_response(code=404, message="找不到达人与活动的关联", data=None)
except Exception as e:
logger.error(f"更新达人状态时出错: {str(e)}")
return api_response(code=500, message=f"更新状态失败: {str(e)}", data=None)
class BrandChatSessionViewSet(viewsets.ModelViewSet):
"""品牌聊天会话API视图集"""
queryset = BrandChatSession.objects.filter(is_active=True)
serializer_class = BrandChatSessionSerializer
authentication_classes = [CustomTokenAuthentication]
permission_classes = [IsAuthenticated]
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
serializer = self.get_serializer(queryset, many=True)
return api_response(data=serializer.data)
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return api_response(data=serializer.data)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
if serializer.is_valid():
self.perform_update(serializer)
return api_response(data=serializer.data)
return api_response(code=400, message="更新失败", data=serializer.errors)
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return api_response(message="删除成功", data=None)
def perform_create(self, serializer):
# 创建聊天会话时,可以设置使用特定品牌下的所有知识库
chat_session = serializer.save()
# 如果没有提供dataset_id_list则使用品牌的dataset_id_list
if not chat_session.dataset_id_list:
brand = chat_session.brand
chat_session.dataset_id_list = brand.dataset_id_list
chat_session.save(update_fields=['dataset_id_list', 'updated_at'])