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
This commit is contained in:
2026-07-05 23:17:38 +08:00
parent 76ea5f8255
commit f1c8633345
54 changed files with 5332 additions and 4494 deletions

View File

@@ -342,6 +342,12 @@ class KefuGetDashouDetailView(APIView):
member_records = Huiyuangoumai.query.filter(
yonghu_id=uid
).order_by('-CreateTime')
# 批量预取会员信息
_huiyuan_ids = [r.huiyuan_id for r in member_records]
_huiyuan_map = {
h.huiyuan_id: h.jieshao
for h in Huiyuan.query.filter(huiyuan_id__in=_huiyuan_ids).only('huiyuan_id', 'jieshao')
}
member_list = []
for record in member_records:
# 检查是否过期
@@ -351,11 +357,7 @@ class KefuGetDashouDetailView(APIView):
is_expired = record.daoqi_time < timezone.now() if record.daoqi_time else True
if not is_expired:
try:
huiyuan = Huiyuan.query.get(huiyuan_id=record.huiyuan_id)
huiyuan_name = huiyuan.jieshao
except Huiyuan.DoesNotExist:
huiyuan_name = '未知会员'
huiyuan_name = _huiyuan_map.get(record.huiyuan_id, '未知会员')
member_list.append({
'id': record.id,
'huiyuan_name': huiyuan_name,
@@ -828,8 +830,12 @@ class KefuGetShangjiaListView(APIView):
return Response({'code': 400, 'msg': '商家状态格式错误'})
# 5. 统计总商家数(应用筛选后)
total = shangjia_qs.count()
valid_merchant_count = shangjia_qs.filter(zhuangtai=1).count()
_agg = shangjia_qs.aggregate(
total=Count('id'),
valid=Count('id', filter=Q(zhuangtai=1)),
)
total = _agg['total']
valid_merchant_count = _agg['valid']
# 6. 分页
offset = (page - 1) * page_size