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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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)