处理超时和获取个人资料相关

This commit is contained in:
dspwasc 2025-04-14 16:35:06 +08:00
parent 58d0c021b3
commit d769f814b4
2 changed files with 439 additions and 144 deletions

View File

@ -13,7 +13,8 @@ from .views import (
RegisterView,
LoginView,
LogoutView,
ChatHistoryViewSet
ChatHistoryViewSet,
user_profile
)
# 创建路由器
@ -39,6 +40,7 @@ urlpatterns = [
# 用户管理相关
path('users/', user_list, name='user-list'),
path('users/profile/', user_profile, name='user-profile'),
path('users/<str:pk>/', user_detail, name='user-detail'),
path('users/<str:pk>/update/', user_update, name='user-update'),
path('users/<str:pk>/delete/', user_delete, name='user-delete'),

View File

@ -803,8 +803,7 @@ class ChatHistoryViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
},
"problem_optimization": False
},
headers={"Content-Type": "application/json"},
timeout=30
headers={"Content-Type": "application/json"}
)
if chat_response.status_code != 200:
@ -832,8 +831,7 @@ class ChatHistoryViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
url=message_url,
json={"message": question, "re_chat": False, "stream": True},
headers={"Content-Type": "application/json"},
stream=True, # 启用流式传输
timeout=60
stream=True # 启用流式传输
)
if message_request.status_code != 200:
@ -1010,8 +1008,7 @@ class ChatHistoryViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
chat_response = requests.post(
url=f"{settings.API_BASE_URL}/api/application/chat/open",
json=chat_request_data,
headers={"Content-Type": "application/json"},
timeout=30
headers={"Content-Type": "application/json"}
)
logger.info(f"API响应状态码: {chat_response.status_code}")
@ -1041,8 +1038,7 @@ class ChatHistoryViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
message_response = requests.post(
url=f"{settings.API_BASE_URL}/api/application/chat_message/{chat_id}",
json=message_request_data,
headers={"Content-Type": "application/json"},
timeout=60
headers={"Content-Type": "application/json"}
)
if message_response.status_code != 200:
@ -1299,7 +1295,6 @@ class ChatHistoryViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
export_response = requests.get(
url=export_url,
timeout=60,
stream=True # 使用流式传输处理大文件
)
@ -1356,8 +1351,7 @@ class ChatHistoryViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
# 调用外部API
response = requests.get(
url=api_url,
params=params,
timeout=30
params=params
)
if response.status_code != 200:
@ -1543,8 +1537,7 @@ class ChatHistoryViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
response = requests.get(
url=url,
params=params,
timeout=30
params=params
)
if response.status_code != 200:
@ -2067,8 +2060,7 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
response = requests.put(
f'{settings.API_BASE_URL}/api/dataset/{instance.external_id}',
json=api_data,
headers={'Content-Type': 'application/json'},
timeout=30
headers={'Content-Type': 'application/json'}
)
if response.status_code != 200:
@ -2080,8 +2072,6 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
logger.info(f"外部知识库更新成功: {instance.external_id}")
except requests.exceptions.Timeout:
raise ExternalAPIError("请求超时,请稍后重试")
except requests.exceptions.RequestException as e:
raise ExternalAPIError(f"API请求失败: {str(e)}")
except Exception as e:
@ -2622,11 +2612,10 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
logger.info(f"调用分割API URL: {url}")
logger.info(f"请求字段: {list(files_data.keys())}")
# 发送请求
# 发送请求 - 移除timeout参数
response = requests.post(
url,
files=files_data,
timeout=60
files=files_data
)
# 记录请求头和响应信息,方便排查问题
@ -2758,7 +2747,7 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
try:
# 简单的验证请求
verify_url = f'{settings.API_BASE_URL}/api/dataset/{instance.external_id}'
verify_response = requests.get(verify_url, timeout=10)
verify_response = requests.get(verify_url)
if verify_response.status_code != 200:
logger.error(f"外部知识库不存在或无法访问: {instance.external_id}, 状态码: {verify_response.status_code}")
return Response({
@ -2919,7 +2908,7 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
# 记录请求数据,方便调试
logger.info(f"上传文档数据: 文档名={doc_data.get('name')}, 段落数={len(doc_data.get('paragraphs', []))}")
# 发送请求
# 发送请求,不设置超时限制
response = requests.post(url, json=doc_data)
# 记录响应结果
@ -2996,8 +2985,7 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
response = requests.post(
f'{settings.API_BASE_URL}/api/dataset',
json=api_data,
headers={'Content-Type': 'application/json'},
timeout=30
headers={'Content-Type': 'application/json'}
)
if response.status_code != 200:
@ -3013,8 +3001,6 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
return dataset_id
except requests.exceptions.Timeout:
raise ExternalAPIError("请求超时,请稍后重试")
except requests.exceptions.RequestException as e:
raise ExternalAPIError(f"API请求失败: {str(e)}")
except Exception as e:
@ -3028,8 +3014,7 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
response = requests.delete(
f'{settings.API_BASE_URL}/api/dataset/{external_id}',
headers={'Content-Type': 'application/json'},
timeout=30
headers={'Content-Type': 'application/json'}
)
logger.info(f"删除外部知识库响应: status_code={response.status_code}, response={response.text}")
@ -3058,9 +3043,6 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
logger.warning(f"外部知识库删除响应无法解析JSON但状态码为200视为成功: {external_id}")
return True
except requests.exceptions.Timeout:
logger.error(f"删除外部知识库超时: {external_id}")
raise ExternalAPIError("请求超时,请稍后重试")
except requests.exceptions.RequestException as e:
logger.error(f"删除外部知识库请求异常: {external_id}, error={str(e)}")
raise ExternalAPIError(f"API请求失败: {str(e)}")
@ -3096,8 +3078,7 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
url = f'{settings.API_BASE_URL}/api/dataset/{instance.external_id}/document'
response = requests.get(
url,
headers={'Content-Type': 'application/json'},
timeout=30
headers={'Content-Type': 'application/json'}
)
if response.status_code != 200:
@ -3224,7 +3205,7 @@ class KnowledgeBaseViewSet(KnowledgeBasePermissionMixin, viewsets.ModelViewSet):
# 调用正确的外部API获取文档段落内容
try:
url = f'{settings.API_BASE_URL}/api/dataset/{knowledge_base.external_id}/document/{document.external_id}/paragraph'
response = requests.get(url, timeout=30)
response = requests.get(url)
if response.status_code != 200:
logger.error(f"获取文档段落内容失败: {response.status_code}, {response.text}")
@ -4239,6 +4220,9 @@ class LoginView(APIView):
# 获取或创建token
token, _ = Token.objects.get_or_create(user=user)
# 登录用户(可选)
login(request, user)
return Response({
"code": 200,
"message": "登录成功",
@ -4246,9 +4230,9 @@ class LoginView(APIView):
"id": str(user.id),
"username": user.username,
"email": user.email,
"name": user.name,
"role": user.role,
"department": user.department,
"name": user.name,
"group": user.group,
"token": token.key
}
@ -4381,7 +4365,7 @@ class RegisterView(APIView):
"code": 200,
"message": "注册成功",
"data": {
"id": user.id,
"id": str(user.id),
"username": user.username,
"email": user.email,
"role": user.role,
@ -4430,28 +4414,111 @@ class LogoutView(APIView):
@api_view(['GET', 'PUT'])
@permission_classes([IsAuthenticated])
def user_profile(request):
"""获取或更新用户信息"""
if request.method == 'GET':
data = {
'id': request.user.id,
'username': request.user.username,
'email': request.user.email,
'role': request.user.role,
'department': request.user.department,
'phone': request.user.phone,
'date_joined': request.user.date_joined
}
return Response(data)
"""
获取或更新当前登录用户信息
elif request.method == 'PUT':
user = request.user
# 只允许更新特定字段
allowed_fields = ['email', 'phone', 'department']
for field in allowed_fields:
if field in request.data:
setattr(user, field, request.data[field])
user.save()
return Response({'message': '用户信息更新成功'})
此接口与user_update的区别:
1. 任何已认证用户可访问
2. 仅能更新当前登录用户自己的信息
3. 不能修改角色等重要字段
4. 不需要指定用户ID自动使用当前用户
"""
try:
if request.method == 'GET':
# 检查用户是否已认证
user = request.user
if not user.is_authenticated:
return Response({
'code': 401,
'message': '用户未认证',
'data': None
}, status=status.HTTP_401_UNAUTHORIZED)
data = {
'id': str(user.id),
'username': user.username,
'email': user.email,
'name': user.name,
'role': user.role,
'department': user.department,
'group': user.group,
'date_joined': user.date_joined.strftime('%Y-%m-%d %H:%M:%S')
}
return Response({
'code': 200,
'message': '获取用户信息成功',
'data': data
})
elif request.method == 'PUT':
# 检查请求数据格式
try:
if not request.data:
return Response({
'code': 400,
'message': '请求数据为空或格式错误',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as data_error:
return Response({
'code': 400,
'message': f'请求数据格式错误: {str(data_error)}。请确保提交的是有效的JSON格式数据属性名必须使用双引号。',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
user = request.user
# 只允许更新特定字段
allowed_fields = ['email', 'name', 'phone', 'department', 'group']
updated_fields = []
for field in allowed_fields:
if field in request.data:
setattr(user, field, request.data[field])
updated_fields.append(field)
if updated_fields:
try:
user.save()
return Response({
'code': 200,
'message': f'用户信息更新成功,已更新字段: {", ".join(updated_fields)}',
'data': {
'id': str(user.id),
'username': user.username,
'email': user.email,
'name': user.name,
'role': user.role,
'department': user.department,
'group': user.group,
}
})
except Exception as save_error:
logger.error(f"保存用户数据失败: {str(save_error)}")
return Response({
'code': 500,
'message': f'更新用户信息失败: {str(save_error)}',
'data': None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
else:
return Response({
'code': 400,
'message': '没有提供任何可更新的字段',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
else:
return Response({
'code': 405,
'message': f'不支持的请求方法: {request.method}',
'data': None
}, status=status.HTTP_405_METHOD_NOT_ALLOWED)
except Exception as e:
logger.error(f"处理用户信息请求失败: {str(e)}")
logger.error(traceback.format_exc())
return Response({
'code': 500,
'message': f'处理请求失败: {str(e)}',
'data': None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@csrf_exempt
@api_view(['POST'])
@ -4513,7 +4580,14 @@ def change_password(request):
@api_view(['POST'])
@permission_classes([AllowAny])
def user_register(request):
"""用户注册"""
"""
[已弃用] 用户注册 - 请使用 RegisterView 类代替
此函数仅保留用于兼容性目的新代码应该使用 /api/auth/register/ 接口
"""
# 打印弃用警告
logger.warning("使用已弃用的user_register函数请改用RegisterView类")
try:
data = request.data
@ -4522,38 +4596,50 @@ def user_register(request):
for field in required_fields:
if not data.get(field):
return Response({
'error': f'缺少必填字段: {field}'
'code': 400,
'message': f'缺少必填字段: {field}',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 验证角色
valid_roles = ['admin', 'leader', 'member']
if data['role'] not in valid_roles:
return Response({
'error': f'无效的角色,必须是: {", ".join(valid_roles)}'
'code': 400,
'message': f'无效的角色,必须是: {", ".join(valid_roles)}',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 如果是组员,必须指定小组
if data['role'] == 'member' and not data.get('group'):
return Response({
'error': '组员必须指定所属小组'
'code': 400,
'message': '组员必须指定所属小组',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 检查用户名是否已存在
if User.objects.filter(username=data['username']).exists():
return Response({
'error': '用户名已存在'
'code': 400,
'message': '用户名已存在',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 检查邮箱是否已存在
if User.objects.filter(email=data['email']).exists():
return Response({
'error': '邮箱已被注册'
'code': 400,
'message': '邮箱已被注册',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 验证密码强度
if len(data['password']) < 8:
return Response({
'error': '密码长度必须至少为8位'
'code': 400,
'message': '密码长度必须至少为8位',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 验证邮箱格式
@ -4561,7 +4647,9 @@ def user_register(request):
validate_email(data['email'])
except ValidationError:
return Response({
'error': '邮箱格式不正确'
'code': 400,
'message': '邮箱格式不正确',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 创建用户
@ -4581,9 +4669,10 @@ def user_register(request):
token, _ = Token.objects.get_or_create(user=user)
return Response({
'code': 200,
'message': '注册成功',
'data': {
'id': user.id,
'id': str(user.id),
'username': user.username,
'email': user.email,
'role': user.role,
@ -4596,82 +4685,41 @@ def user_register(request):
}, status=status.HTTP_201_CREATED)
except Exception as e:
print(f"注册失败: {str(e)}")
print(f"错误类型: {type(e)}")
print(f"错误堆栈: {traceback.format_exc()}")
logger.error(f"注册失败: {str(e)}")
logger.error(f"错误类型: {type(e)}")
logger.error(f"错误堆栈: {traceback.format_exc()}")
return Response({
'error': f'注册失败: {str(e)}',
'code': 500,
'message': f'注册失败: {str(e)}',
'data': None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@csrf_exempt
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def verify_token(request):
"""验证令牌有效性"""
try:
return Response({
"code": 200,
"message": "令牌有效",
"data": {
"is_valid": True,
"user": {
"id": request.user.id,
"username": request.user.username,
"email": request.user.email,
"role": request.user.role,
"department": request.user.department,
"name": request.user.name,
"group": request.user.group
}
}
})
except Exception as e:
return Response({
"code": 500,
"message": f"验证失败: {str(e)}",
"data": None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_list(request):
"""获取用户列表"""
user = request.user
if user.role == 'admin':
users = User.objects.all()
elif user.role == 'leader':
users = User.objects.filter(department=user.department)
else:
users = User.objects.filter(id=user.id)
data = [{
'id': u.id,
'username': u.username,
'email': u.email,
'role': u.role,
'department': u.department,
'is_active': u.is_active,
'date_joined': u.date_joined
} for u in users]
return Response(data)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_detail(request, pk):
"""获取用户详情"""
try:
# 尝试转换为 UUID
if not isinstance(pk, uuid.UUID):
try:
pk = uuid.UUID(pk)
except ValueError:
return Response({
"code": 400,
"message": "无效的用户ID格式",
"data": None
}, status=status.HTTP_400_BAD_REQUEST)
# 尝试转换为 UUID处理多种可能的格式
try:
if not isinstance(pk, uuid.UUID):
# 移除所有空格,以防万一
pk = pk.strip()
# 处理带连字符和不带连字符的格式
if '-' not in pk and len(pk) == 32:
# 转换没有连字符的UUID格式
pk_with_hyphens = f"{pk[0:8]}-{pk[8:12]}-{pk[12:16]}-{pk[16:20]}-{pk[20:]}"
pk = uuid.UUID(pk_with_hyphens)
else:
# 尝试直接转换
pk = uuid.UUID(pk)
except ValueError:
# 提供更详细的错误信息
return Response({
"code": 400,
"message": f"无效的用户ID格式: {pk}。用户ID应为有效的UUID格式。",
"data": None
}, status=status.HTTP_400_BAD_REQUEST)
user = get_object_or_404(User, pk=pk)
@ -4689,6 +4737,8 @@ def user_detail(request, pk):
}
})
except Exception as e:
logger.error(f"获取用户信息失败: {str(e)}")
logger.error(traceback.format_exc())
return Response({
"code": 500,
"message": f"获取用户信息失败: {str(e)}",
@ -4698,27 +4748,270 @@ def user_detail(request, pk):
@api_view(['PUT'])
@permission_classes([IsAdminUser])
def user_update(request, pk):
"""更新用户信息"""
"""
管理员更新用户信息
此接口与user_profile的区别:
1. 仅管理员可访问
2. 可以更新任何用户的信息
3. 可以修改角色等重要字段
4. 需要在URL中指定用户ID
"""
try:
user = User.objects.get(pk=pk)
# 检查请求数据格式
try:
if not request.data:
return Response({
'code': 400,
'message': '请求数据为空或格式错误',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as data_error:
return Response({
'code': 400,
'message': f'请求数据格式错误: {str(data_error)}。请确保提交的是有效的JSON格式数据属性名必须使用双引号。',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
# 尝试转换为 UUID
try:
if not isinstance(pk, uuid.UUID):
pk = pk.strip()
# 处理带连字符和不带连字符的格式
if '-' not in pk and len(pk) == 32:
# 转换没有连字符的UUID格式
pk_with_hyphens = f"{pk[0:8]}-{pk[8:12]}-{pk[12:16]}-{pk[16:20]}-{pk[20:]}"
pk = uuid.UUID(pk_with_hyphens)
else:
# 尝试直接转换
pk = uuid.UUID(pk)
except ValueError:
return Response({
"code": 400,
"message": f"无效的用户ID格式: {pk}。用户ID应为有效的UUID格式。",
"data": None
}, status=status.HTTP_400_BAD_REQUEST)
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
return Response({
'code': 404,
'message': '用户不存在',
'data': None
}, status=status.HTTP_404_NOT_FOUND)
# 只允许更新特定字段
allowed_fields = ['email', 'role', 'department', 'is_active', 'phone']
allowed_fields = ['email', 'role', 'department', 'group', 'is_active', 'phone', 'name']
updated_fields = []
for field in allowed_fields:
if field in request.data:
setattr(user, field, request.data[field])
updated_fields.append(field)
if not updated_fields:
return Response({
'code': 400,
'message': '没有提供任何可更新的字段',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
user.save()
return Response({'message': '用户信息更新成功'})
except User.DoesNotExist:
return Response({'message': '用户不存在'}, status=404)
return Response({
'code': 200,
'message': '用户信息更新成功',
'data': {
'id': str(user.id),
'username': user.username,
'email': user.email,
'name': user.name,
'role': user.role,
'department': user.department,
'group': user.group,
'is_active': user.is_active
}
})
except Exception as e:
logger.error(f"更新用户信息失败: {str(e)}")
logger.error(traceback.format_exc())
return Response({
'code': 500,
'message': f'更新用户信息失败: {str(e)}',
'data': None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['DELETE'])
@permission_classes([IsAdminUser])
def user_delete(request, pk):
"""删除用户"""
try:
user = User.objects.get(pk=pk)
user.delete()
return Response({'message': '用户删除成功'})
except User.DoesNotExist:
return Response({'message': '用户不存在'}, status=404)
# 尝试转换为 UUID
try:
if not isinstance(pk, uuid.UUID):
pk = pk.strip()
# 处理带连字符和不带连字符的格式
if '-' not in pk and len(pk) == 32:
# 转换没有连字符的UUID格式
pk_with_hyphens = f"{pk[0:8]}-{pk[8:12]}-{pk[12:16]}-{pk[16:20]}-{pk[20:]}"
pk = uuid.UUID(pk_with_hyphens)
else:
# 尝试直接转换
pk = uuid.UUID(pk)
except ValueError:
return Response({
"code": 400,
"message": f"无效的用户ID格式: {pk}。用户ID应为有效的UUID格式。",
"data": None
}, status=status.HTTP_400_BAD_REQUEST)
try:
user = User.objects.get(pk=pk)
except User.DoesNotExist:
return Response({
'code': 404,
'message': '用户不存在',
'data': None
}, status=status.HTTP_404_NOT_FOUND)
# 检查是否试图删除管理员账户
if user.is_superuser or user.role == 'admin':
return Response({
'code': 403,
'message': '不允许删除管理员账户',
'data': None
}, status=status.HTTP_403_FORBIDDEN)
# 删除用户
username = user.username
user.delete()
return Response({
'code': 200,
'message': f'用户 {username} 删除成功',
'data': None
})
except Exception as e:
logger.error(f"删除用户失败: {str(e)}")
logger.error(traceback.format_exc())
return Response({
'code': 500,
'message': f'删除用户失败: {str(e)}',
'data': None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@csrf_exempt
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def verify_token(request):
"""验证令牌有效性"""
try:
return Response({
"code": 200,
"message": "令牌有效",
"data": {
"is_valid": True,
"user": {
"id": str(request.user.id),
"username": request.user.username,
"email": request.user.email,
"name": request.user.name,
"role": request.user.role,
"department": request.user.department,
"group": request.user.group
}
}
})
except Exception as e:
logger.error(f"验证令牌失败: {str(e)}")
logger.error(traceback.format_exc())
return Response({
"code": 500,
"message": f"验证失败: {str(e)}",
"data": None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def user_list(request):
"""获取用户列表"""
try:
# 获取查询参数
page = int(request.query_params.get('page', 1))
page_size = int(request.query_params.get('page_size', 20))
keyword = request.query_params.get('keyword', '')
# 根据用户角色获取不同范围的用户列表
user = request.user
base_query = User.objects.all()
if user.role == 'admin':
users_query = base_query
elif user.role == 'leader':
users_query = base_query.filter(department=user.department)
else:
users_query = base_query.filter(id=user.id)
# 添加关键字搜索
if keyword:
users_query = users_query.filter(
Q(username__icontains=keyword) |
Q(email__icontains=keyword) |
Q(name__icontains=keyword) |
Q(department__icontains=keyword)
)
# 计算总数
total = users_query.count()
# 分页
start = (page - 1) * page_size
end = start + page_size
users = users_query[start:end]
# 构造数据
user_data = []
for u in users:
user_data.append({
'id': str(u.id),
'username': u.username,
'email': u.email,
'name': u.name,
'role': u.role,
'department': u.department,
'group': u.group,
'is_active': u.is_active,
'date_joined': u.date_joined.strftime('%Y-%m-%d %H:%M:%S')
})
return Response({
'code': 200,
'message': '获取用户列表成功',
'data': {
'total': total,
'page': page,
'page_size': page_size,
'users': user_data
}
})
except ValueError as e:
# 处理参数转换错误
return Response({
'code': 400,
'message': f'参数错误: {str(e)}',
'data': None
}, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
logger.error(f"获取用户列表失败: {str(e)}")
logger.error(traceback.format_exc())
return Response({
'code': 500,
'message': f'获取用户列表失败: {str(e)}',
'data': None
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)