Files
Django/rank/views/biaoqian.py
TermiNexus f1c8633345 perf: P1 性能优化批量修复 + kefu 视图拆分
P1 性能优化(避免循环内 N+1 / N 次 DB 查询):
- shop_order_views._batch_images: 移除 ThreadPoolExecutor 掩盖的 N 次查询,改单次批量 + Python 侧分组
- product_query.DashouHuiyuanList: 5N 查询 -> 3 次批量预取 + 本地闭包判断
- roles.GetRolePermissionView / 用户列表: 循环内 RolePermission/Permission/UserRole/Role -> 批量 __in 预取
- guanli / zuzhang 杜次分红 4.2/4.3: 循环内 update_or_create + 单条 delete -> bulk_create + bulk_update + 批量 delete
- admin_config QQ 群配置: 循环内 exists/first/save/create -> 批量预取 + bulk_create + bulk_update
- jituan 服务层多处合并统计查询、批量预取 map
- rank 多处循环 N+1 改批量预取
- backend 多处循环内 count/create 改批量
- config/orders/merchant_ops 多处循环 N+1 改批量预取

其他改动:
- users/views/kefu.py 拆分为 kefu_base/kefu_dashou/kefu_orders/kefu_punishment/kefu_withdraw 5 个文件
- 删除遗留脚本 check_prod_uid.py / create_rbac_tables.sql
2026-07-05 23:17:38 +08:00

192 lines
7.6 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.
"""rank.views.biaoqian - auto-generated by split script."""
import json
import logging
from decimal import Decimal
from django.db import models, transaction
from django.db.models import F, Prefetch
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from ..utils import get_tag_fee, create_shenhe_jilu, validate_shenheguan
from ..models import (
YonghuChenghao, Chenghao, KaoheCishuFeiyong, KaoheJujueJilu,
KaoheguanBankuai, Bankuai, ShenheJilu, KaoheJiluFeiyong
)
from users.models import UserShenheguan, UserDashou
from users.business_models import User
from products.models import ShangpinLeixing
logger = logging.getLogger(__name__)
class DashouBiaoqianView(APIView):
"""获取当前打手所有称号标签"""
permission_classes = [IsAuthenticated]
def post(self, request):
try:
yonghu = request.user
# 查询用户的所有称号关联,一次连表取出
relations = YonghuChenghao.objects.filter(
yonghu=yonghu
).select_related('chenghao')
chenghao_list = []
for rel in relations:
ch = rel.chenghao
# 解析特效描述 JSON前端需要对象
texiao_json = {}
if ch.texiao_miaoshu:
try:
texiao_json = json.loads(ch.texiao_miaoshu)
except json.JSONDecodeError:
texiao_json = {}
chenghao_list.append({
'mingcheng': ch.mingcheng,
'tubiao_url': ch.tubiao_url or '',
'texiao_json': texiao_json,
})
return Response({
'code': 0,
'msg': '成功',
'data': {'chenghao_list': chenghao_list}
})
except Exception as e:
logger.error(f"获取打手标签失败: {e}", exc_info=True)
return Response({'code': 1, 'msg': '服务器错误', 'data': None})
class BankuaiBiaoqianView(APIView):
"""获取商品类型所属板块的所有标签"""
permission_classes = [IsAuthenticated]
def post(self, request):
leixing_id = request.data.get('leixing_id') or request.data.get('ProductTypeID')
if not leixing_id:
return Response({'code': 1, 'msg': '缺少leixing_id'})
try:
leixing = ShangpinLeixing.objects.select_related('bankuai').get(id=leixing_id)
except ShangpinLeixing.DoesNotExist:
return Response({'code': 2, 'msg': '商品类型不存在'})
bankuai = leixing.bankuai
if not bankuai:
return Response({'code': 0, 'data': {'biaoqian_list': []}})
# 获取该板块下所有类型的标签leixing可以为dashou/shangjia等这里先返回所有
chenghao_list = Chenghao.objects.filter(bankuai=bankuai, leixing='dashou')
data = []
from jituan.services.club_context import resolve_effective_club_id
from jituan.services.club_kaohe_chenghao import filter_chenghao_ids_for_pool
club_id = resolve_effective_club_id(request, request.user)
allowed_ids = set(
filter_chenghao_ids_for_pool(club_id, list(chenghao_list.values_list('id', flat=True)))
)
for ch in chenghao_list:
if ch.id not in allowed_ids:
continue
texiao_json = {}
if ch.texiao_miaoshu:
try:
texiao_json = json.loads(ch.texiao_miaoshu)
except:
pass
data.append({
'id': ch.id,
'mingcheng': ch.mingcheng,
'texiao_json': texiao_json
})
return Response({'code': 0, 'data': {'biaoqian_list': data}})
class KaoheJinpaiTagsView(APIView):
"""获取考核金牌页面的标签和板块信息"""
permission_classes = [IsAuthenticated]
def post(self, request):
try:
user = request.user
# 获取用户已拥有的标签名称集合
owned_names = set(
YonghuChenghao.objects.filter(yonghu=user, chenghao__leixing='dashou')
.values_list('chenghao__mingcheng', flat=True)
)
# 板块列表prefetch 一次性加载标签和费用,避免三层嵌套 N+1
plate_list = []
all_bankuai = Bankuai.objects.prefetch_related(
Prefetch(
'chenghao_set',
queryset=Chenghao.objects.filter(leixing='dashou').prefetch_related(
Prefetch(
'kaohecishufeiyong_set',
queryset=KaoheCishuFeiyong.objects.order_by('cishu'),
)
),
to_attr='dashou_tags'
)
).all()
for bk in all_bankuai:
tag_list = []
for tag in getattr(bk, 'dashou_tags', []):
# 费用列表(已预加载,保持 cishu 升序)
fee_list = [{'cishu': f.cishu, 'feiyong': float(f.feiyong)}
for f in tag.kaohecishufeiyong_set.all()]
# 若没有记录,补充默认费用
if not fee_list:
fee_list = [{'cishu': 1, 'feiyong': 5.00}]
tag_list.append({
'id': tag.id,
'name': tag.mingcheng,
'texiao_json': json.loads(tag.texiao_miaoshu) if tag.texiao_miaoshu else {},
'jinpai': tag.kaioi_jinpai,
'rule': tag.kaohe_guize or '',
'fee_list': fee_list,
'owned': tag.mingcheng in owned_names,
})
if tag_list:
plate_list.append({
'bankuai_id': bk.bankuai_id,
'mingcheng': bk.mingcheng,
'tags': tag_list
})
# 新增:返回所有在职考核官信息(用于指定考核官)
kaoheguan_list = []
# select_related 预加载 OneToOne 反向关系 DashouProfile避免循环内 N+1
for kg in UserShenheguan.objects.filter(zhuangtai=1).select_related('user', 'user__DashouProfile'):
uid = kg.user.UserUID
avatar = kg.user.Avatar or ''
# 获取考核官的打手昵称(从打手扩展表,已预加载)
dashou_nick = ''
dashou_prof = getattr(kg.user, 'DashouProfile', None)
if dashou_prof:
dashou_nick = dashou_prof.nicheng or ''
kaoheguan_list.append({
'yonghuid': uid,
'avatar': avatar,
'dashou_nick': dashou_nick,
'is_renzheng': kg.is_renzheng,
'shenhe_zhuangtai': kg.shenhe_zhuangtai,
})
return Response({
'code': 0,
'data': {
'plate_list': plate_list,
'my_tags': list(owned_names),
'kaoheguan_list': kaoheguan_list, # 新增
}
})
except Exception as e:
return Response({'code': 500, 'msg': str(e)}, status=500)