import random from django.shortcuts import render from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status import openpyxl from .models import Students from .models import Pledge from channels.layers import get_channel_layer from asgiref.sync import async_to_sync from django.http import JsonResponse from decimal import Decimal from django.http import HttpResponse from django.db.models import Min, Max from django.db import transaction # class TestView(APIView): # def get(self, request): # data = { # "message": "Hello from Django!", # "status": "success" # } # return Response(data, status=status.HTTP_200_OK) # @api_view(['POST']) # def upload_students(request): # # 获取上传的文件 # file = request.FILES.get('file') # # if not file: # return Response({'error': '没有上传文件'}, status=status.HTTP_400_BAD_REQUEST) # # try: # # 读取 Excel 文件 # wb = openpyxl.load_workbook(file) # sheet = wb.active # # # 遍历 Excel 表格的每一行,并保存到数据库 # for row in sheet.iter_rows(min_row=2, values_only=True): # sid, name = row[0], row[1] # # # 使用 update_or_create 保存到数据库 # Students.objects.update_or_create( # sid=sid, # defaults={'name': name, 'score': 0} # ) # # return Response({'message': '导入成功!'}, status=status.HTTP_200_OK) # # except Exception as e: # return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) @api_view(['POST']) def upload_students(request): file = request.FILES.get('file') if not file: return Response({'error': '没有上传文件'}, status=status.HTTP_400_BAD_REQUEST) try: wb = openpyxl.load_workbook(file) sheet = wb.active # 使用列表收集学生数据 students_data = [] for row in sheet.iter_rows(min_row=2, values_only=True): sid, name = row[0], row[1] students_data.append(Students(sid=sid, name=name, score=0)) # 开始一个事务 with transaction.atomic(): # 清空表 Students.objects.all().delete() # 批量插入学生数据 Students.objects.bulk_create(students_data) return Response({'message': '导入成功!'}, status=status.HTTP_200_OK) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) @api_view(['GET']) def get_student_info(request, student_id): try: student = Students.objects.get(sid=student_id) return JsonResponse({'name': student.name, 'score': student.score}) except Students.DoesNotExist: return JsonResponse({'error': 'Student not found'}, status=404) @api_view(['POST']) def update_student_score(request): student_id = request.data.get('student_id') score = request.data.get('score') try: student = Students.objects.get(sid=student_id) student.score = Decimal(score) # 将分数转换为 Decimal 类型 student.save() return JsonResponse({'success': True}) except Students.DoesNotExist: return JsonResponse({'error': 'Student not found'}, status=404) except Exception as e: return JsonResponse({'error': str(e)}, status=500) @api_view(['GET']) def get_student_info_by_name(request, student_name): try: student = Students.objects.get(name=student_name) # 根据姓名查询学生 return JsonResponse({'name': student.name, 'score': student.score}) except Students.DoesNotExist: return JsonResponse({'error': 'Student not found'}, status=404) @api_view(['POST']) def send_exemption_card(request): student_id = request.data.get('studentId') student_name = request.data.get('studentName') new_score = request.data.get('newScore') try: student = Students.objects.get(sid=student_id) student.score = new_score # 更新积分 student.save() return JsonResponse({'message': '豁免卡信息处理成功'}, status=200) except Students.DoesNotExist: return JsonResponse({'error': '学生未找到'}, status=404) @api_view(['GET']) def leaderboard(request): # 获取积分排名前5的学生 top_students = Students.objects.order_by('-score')[:5] leaderboard_data = [{'name': student.name, 'score': student.score} for student in top_students] return JsonResponse(leaderboard_data, safe=False) @api_view(['POST']) def create_pledge(request): student_id = request.data.get('studentId') student_name = request.data.get('studentName') pledge_score = request.data.get('pledgeScore') if not student_id or not student_name or not pledge_score: return Response({'error': '所有字段都是必需的'}, status=status.HTTP_400_BAD_REQUEST) pledge = Pledge.objects.create( student_id=student_id, student_name=student_name, pledge_score=pledge_score, status=0 # 设置状态为 0,表示未完成 ) return Response({'message': '典当信息已保存', 'pledge_id': pledge.id}, status=status.HTTP_201_CREATED) @api_view(['POST']) def update_question_score(request): student_id = request.data.get('studentId') question_score = request.data.get('questionScore') print(request.data) try: student = Students.objects.get(sid=student_id) # student = Students.objects.prefetch_related('pledges').get(sid=student_id) student.score += Decimal(question_score) # 直接增加教师给的积分 student.save() # 保存更新后的积分 pledge = Pledge.objects.filter(student_id=student_id).order_by('-created_at').first() # pledge = student.pledges.order_by('-created_at').first() if pledge: if pledge.status == 0: # 典当状态为0 pledge_score_decimal = Decimal(pledge.pledge_score) # 获取典当的积分 if question_score >= 2: student.score += pledge_score_decimal * Decimal(2) # 加倍典当积分 else: student.score -= pledge_score_decimal # 减去典当积分 pledge.status = 1 # 更新典当状态为1 pledge.save() # 保存更新后的典当状态 student.save() # 保存最终的学生积分 # 返回积分和典当信息 return Response({ 'message': '积分更新成功', 'current_score': str(student.score), 'pledge_score': str(pledge.pledge_score), 'pledge_status': pledge.status, }, status=status.HTTP_200_OK) else: # 返回更新后的积分和初始积分 return Response({ 'message': '积分更新成功,但没有新的典当信息', 'updated_score': str(student.score), }, status=status.HTTP_200_OK) else: return Response({ 'updated_score': str(student.score), }, status=status.HTTP_200_OK) except Students.DoesNotExist: return Response({'error': '学生不存在'}, status=status.HTTP_404_NOT_FOUND) except Exception as e: return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) # 定义导出学生数据的 API 视图,接受 POST 请求 @api_view(['POST']) def export_students_scores(request): try: # 获取所有学生信息 students = Students.objects.all() # 找到最低和最高积分用于计算百分比 min_score = students.aggregate(min_score=Min('score'))['min_score'] max_score = students.aggregate(max_score=Max('score'))['max_score'] # 处理为百分比 def calculate_percentage(score, min_score, max_score): if max_score == min_score: # 避免分母为0 return 50 # 所有学生得分相同时,统一设为50% return (score - min_score) / (max_score - min_score) * 100 # 创建 Excel 工作簿 wb = openpyxl.Workbook() ws = wb.active ws.title = "学生积分百分比" # 写入表头 ws.append(["学号", "姓名", "积分", "百分比"]) # 写入每个学生的信息 for student in students: percentage = calculate_percentage(student.score, min_score, max_score) ws.append([student.sid, student.name, float(student.score), f"{percentage:.2f}%"]) # 保存 Excel 文件 response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') response['Content-Disposition'] = 'attachment; filename=students_scores.xlsx' wb.save(response) return response except Exception as e: return Response({'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)