You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
9.0 KiB

1 month ago
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)