third commit

main
Lyanling 2 months ago
parent 04a9e09679
commit e85ced7137

@ -25,7 +25,7 @@ SECRET_KEY = 'django-insecure-50h(t$5-#_$h(#7)bdr-fr2)77c+v1$=n_0b82$z#*od_$_%ia
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['*']
# Application definition
@ -37,7 +37,9 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls'
'polls',
'rest_framework',
'drf_spectacular',
]
MIDDLEWARE = [
@ -128,3 +130,7 @@ STATIC_URL = '/static/'
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema', # 使用 drf-spectacular 生成接口
}

@ -15,9 +15,11 @@ Including another URLconf
"""
from django.contrib import admin
from django.urls import path,include
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
path('api/schema/', SpectacularAPIView.as_view(), name='schema'), # OpenAPI schema 路由
path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'), # Swagger 文档路由
]

@ -1,4 +1,4 @@
# Generated by Django 3.2.25 on 2024-10-07 08:05
# Generated by Django 3.2.25 on 2024-10-08 09:49
from django.db import migrations, models
@ -18,6 +18,7 @@ class Migration(migrations.Migration):
('student_id', models.CharField(max_length=100, unique=True)),
('score', models.FloatField(default=0)),
('attendance_count', models.IntegerField(default=0)),
('called_count', models.IntegerField(default=0)),
],
),
]

@ -1,18 +0,0 @@
# Generated by Django 3.2.25 on 2024-10-07 16:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('polls', '0002_student'),
]
operations = [
migrations.AddField(
model_name='student',
name='called_count',
field=models.IntegerField(default=0),
),
]

@ -1,18 +0,0 @@
# Generated by Django 3.2.25 on 2024-10-07 16:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('polls', '0003_student_called_count'),
]
operations = [
migrations.AddField(
model_name='student',
name='protected',
field=models.BooleanField(default=False),
),
]

@ -0,0 +1,7 @@
from rest_framework import serializers
from .models import Student # 你需要根据你的模型导入相应的类
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ['name', 'student_id', 'score', 'attendance_count', 'called_count'] # 根据你的模型字段进行调整

@ -1,5 +1,10 @@
from django.urls import path
from django.urls import path,include
from . import views
from rest_framework.routers import DefaultRouter
# router = DefaultRouter()
# router.register(r'students', views.StudentViewSet) # 注册 'students' 路由
urlpatterns = [
path('',views.toLogin_view),
path('index/',views.Login_view),
@ -9,4 +14,5 @@ urlpatterns = [
path('roll_call/', views.roll_call, name='roll_call'),
path('confirm_roll_call/', views.confirm_roll_call, name='confirm_roll_call'), # 确认点名
path('leaderboard/', views.leaderboard, name='leaderboard'),
# path('', include(router.urls)),
]

@ -1,45 +1,252 @@
# from django.shortcuts import render
# from django.http import HttpResponse
# from .models import *
# from django.shortcuts import render, redirect, get_object_or_404
# import random
# import pandas as pd
# from django.db.models import Window, F
# from django.db.models.functions import Rank
# # 导入表单
# from .forms import UploadFileForm
#
# from rest_framework import viewsets
# from .serializers import StudentSerializer
#
# from rest_framework.response import Response
# from rest_framework.decorators import api_view
# # Create your views here.
# def toLogin_view(request):
# return render(request,'login.html')
# def Login_view(request):
# u=request.POST.get("user",'')
# p=request.POST.get("pwd",'')
#
# if u and p:
# c=StudentInfo.objects.filter(stu_name=u,stu_pwd=p).count()
# if c >= 1:
# return HttpResponse("登录成功!")
# else:
# return HttpResponse("账号密码错误!")
# else:
# return HttpResponse("请输入正确的账号和密码!")
#
# def toregister_view(request):
# return render(request, 'register.html')
#
# # #点击注册后做的逻辑判断
# def register_view(request):
# u = request.POST.get("user", '')
# p = request.POST.get("pwd", '')
# if u and p:
# stu = StudentInfo(stu_id=random.choice('0123456789'),stu_name=u, stu_pwd=p)
# stu.save()
# return HttpResponse("注册成功")
# else:
# return HttpResponse("请输入完整的账号和密码!")
#
# #导入excel
# # 上传学生名单的视图
# def upload_students(request):
# if request.method == 'POST':
# form = UploadFileForm(request.POST, request.FILES)
# if form.is_valid():
# # 读取上传的 Excel 文件
# excel_file = request.FILES['file']
# df = pd.read_excel(excel_file) # 使用 pandas 读取 Excel 文件
#
# # 遍历 DataFrame将每个学生保存到数据库
# for _, row in df.iterrows():
# student_id = row['student_id']
# name = row['name']
# Student.objects.get_or_create(student_id=student_id, name=name) # 如果学生已存在则不创建
#
# return redirect('roll_call') # 完成后重定向到点名页面
# else:
# form = UploadFileForm()
#
# return render(request, 'upload_students.html', {'form': form}) # 渲染上传页面
#
# # 开始点名的视图
# def roll_call(request):
# students = Student.objects.all() # 获取所有学生
# selected_student = None # 初始化被选中的学生
#
# # 当教师点击“开始点名”按钮时
# if request.method == 'POST' and 'start_roll_call' in request.POST:
# # 设置权重:总分越高,被点名的概率越低
# weights = [1 / (student.score + 1) for student in students] # 根据分数调整被点名概率
# selected_student = random.choices(students, weights=weights, k=1)[0] # 随机选择一个学生
# request.session['selected_student_id'] = selected_student.student_id # 存储被点名学生的ID到session中
# return redirect('confirm_roll_call') # 跳转到确认点名页面
#
# return render(request, 'roll_call.html', {'selected_student': selected_student}) # 渲染点名页面
#
# # 确认点名的视图
# # def confirm_roll_call(request):
# # # 从 session 中获取被点名的学生
# # student_id = request.session.get('selected_student_id')
# # student = get_object_or_404(Student, student_id=student_id)
# #
# # if request.method == 'POST':
# # # 学生是否到课
# # if 'attended' in request.POST: # 如果选择了到课
# # student.score += 1 # 到课加1分
# # student.attendance_count += 1 # 到课次数加1
# #
# # # 处理是否准确重复问题
# # if request.POST['question_repeat'] == 'accurate':
# # student.score += 0.5 # 重复问题准确加0.5分
# # else:
# # student.score -= 1 # 重复问题不准确扣1分
# #
# # # 处理回答问题的准确性0-3分
# # answer_accuracy = float(request.POST.get('answer_accuracy', 0))
# # student.score += answer_accuracy # 根据回答准确性加分
# # else:
# # student.score -= 5 # 未到课扣5分
# #
# # student.save() # 保存更新后的学生信息
# # return redirect('roll_call') # 返回点名页面,进行下一轮点名
# #
# # return render(request, 'confirm_roll_call.html', {'student': student}) # 渲染确认点名页面
# def confirm_roll_call(request):
# student_id = request.session.get('selected_student_id')
# student = get_object_or_404(Student, student_id=student_id)
# protection_awarded = False # 初始化保护权标志
#
# if request.method == 'POST':
# # 增加学生的被点名次数
# student.called_count += 1
#
# # 检查学生是否有“保护权”
# if student.called_count % 3 == 0:
# # 如果被点名次数是3的倍数赋予保护权自动加2分
# student.score += 2
# protection_awarded = True # 设置保护权标志
# print(f"Student {student.name} ({student.student_id})获得保护权自动加2分")
# else:
# # 学生是否到课
# if 'attended' in request.POST: # 如果选择了到课
# student.score += 1 # 到课加1分
# student.attendance_count += 1 # 到课次数加1
#
# # 处理是否准确重复问题
# if request.POST['question_repeat'] == 'accurate':
# student.score += 0.5 # 重复问题准确加0.5分
# else:
# student.score -= 1 # 重复问题不准确扣1分
#
# # 处理回答问题的准确性0-3分
# answer_accuracy = float(request.POST.get('answer_accuracy', 0))
# student.score += answer_accuracy # 根据回答准确性加分
# else:
# student.score -= 5 # 未到课扣5分
#
# # 保存更新后的学生信息
# student.save()
# return redirect('roll_call') # 返回点名页面,进行下一轮点名
#
# return render(request, 'confirm_roll_call.html', {'student': student, 'protection_awarded': protection_awarded}) # 渲染确认点名页面
#
#
#
#
# # 积分排行榜
# def leaderboard(request):
# students = Student.objects.all().order_by('-score') # 按分数降序排列
# return render(request, 'leaderboard.html', {'students': students})
#
#
# class StudentViewSet(viewsets.ModelViewSet):
# queryset = Student.objects.all() # 获取所有学生数据
# serializer_class = StudentSerializer # 指定序列化器
from django.shortcuts import render
from django.http import HttpResponse
from .models import *
from django.shortcuts import render, redirect, get_object_or_404
import random
from django.http import JsonResponse
import pandas as pd
from django.db.models import Window, F
from django.db.models.functions import Rank
from django.shortcuts import get_object_or_404
# 导入表单
from .forms import UploadFileForm
# Create your views here.
def toLogin_view(request):
return render(request,'login.html')
# def Login_view(request):
# u=request.POST.get("user",'')
# p=request.POST.get("pwd",'')
#
# if u and p:
# c=StudentInfo.objects.filter(stu_name=u,stu_pwd=p).count()
# if c >= 1:
# return HttpResponse("登录成功!")
# else:
# return HttpResponse("账号密码错误!")
# else:
# return HttpResponse("请输入正确的账号和密码!")
def Login_view(request):
u=request.POST.get("user",'')
p=request.POST.get("pwd",'')
u = request.POST.get("user", '')
p = request.POST.get("pwd", '')
if u and p:
c=StudentInfo.objects.filter(stu_name=u,stu_pwd=p).count()
c = StudentInfo.objects.filter(stu_name=u, stu_pwd=p).count()
if c >= 1:
return HttpResponse("登录成功!")
return JsonResponse({"message": "登录成功!"})
else:
return HttpResponse("账号密码错误!")
return JsonResponse({"message": "账号密码错误!"}, status=400)
else:
return HttpResponse("请输入正确的账号和密码!")
return JsonResponse({"message": "请输入正确的账号和密码!"}, status=400)
def toregister_view(request):
return render(request, 'register.html')
# #点击注册后做的逻辑判断
# def register_view(request):
# u = request.POST.get("user", '')
# p = request.POST.get("pwd", '')
# if u and p:
# stu = StudentInfo(stu_id=random.choice('0123456789'),stu_name=u, stu_pwd=p)
# stu.save()
# return HttpResponse("注册成功")
# else:
# return HttpResponse("请输入完整的账号和密码!")
def register_view(request):
u = request.POST.get("user", '')
p = request.POST.get("pwd", '')
if u and p:
stu = StudentInfo(stu_id=random.choice('0123456789'),stu_name=u, stu_pwd=p)
stu = StudentInfo(stu_id=random.choice('0123456789'), stu_name=u, stu_pwd=p)
stu.save()
return HttpResponse("注册成功")
return JsonResponse({"message": "注册成功"})
else:
return HttpResponse("请输入完整的账号和密码!")
return JsonResponse({"message": "请输入完整的账号和密码!"}, status=400)
#导入excel
# 上传学生名单的视图
# def upload_students(request):
# if request.method == 'POST':
# form = UploadFileForm(request.POST, request.FILES)
# if form.is_valid():
# # 读取上传的 Excel 文件
# excel_file = request.FILES['file']
# df = pd.read_excel(excel_file) # 使用 pandas 读取 Excel 文件
#
# # 遍历 DataFrame将每个学生保存到数据库
# for _, row in df.iterrows():
# student_id = row['student_id']
# name = row['name']
# Student.objects.get_or_create(student_id=student_id, name=name) # 如果学生已存在则不创建
#
# return redirect('roll_call') # 完成后重定向到点名页面
# else:
# form = UploadFileForm()
#
# return render(request, 'upload_students.html', {'form': form}) # 渲染上传页面
def upload_students(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
@ -54,13 +261,28 @@ def upload_students(request):
name = row['name']
Student.objects.get_or_create(student_id=student_id, name=name) # 如果学生已存在则不创建
return redirect('roll_call') # 完成后重定向到点名页面
return JsonResponse({"message": "学生信息上传成功!"})
else:
form = UploadFileForm()
return render(request, 'upload_students.html', {'form': form}) # 渲染上传页面
return render(request, 'upload_students.html', {'form': form}) # 确保在GET请求时返回HttpResponse
# 开始点名的视图
# return render(request, 'upload_students.html', {'form': form}) # 渲染上传页面
# # 开始点名的视图
# def roll_call(request):
# students = Student.objects.all() # 获取所有学生
# selected_student = None # 初始化被选中的学生
#
# # 当教师点击“开始点名”按钮时
# if request.method == 'POST' and 'start_roll_call' in request.POST:
# # 设置权重:总分越高,被点名的概率越低
# weights = [1 / (student.score + 1) for student in students] # 根据分数调整被点名概率
# selected_student = random.choices(students, weights=weights, k=1)[0] # 随机选择一个学生
# request.session['selected_student_id'] = selected_student.student_id # 存储被点名学生的ID到session中
# return redirect('confirm_roll_call') # 跳转到确认点名页面
#
# return render(request, 'roll_call.html', {'selected_student': selected_student}) # 渲染点名页面
def roll_call(request):
students = Student.objects.all() # 获取所有学生
selected_student = None # 初始化被选中的学生
@ -71,10 +293,9 @@ def roll_call(request):
weights = [1 / (student.score + 1) for student in students] # 根据分数调整被点名概率
selected_student = random.choices(students, weights=weights, k=1)[0] # 随机选择一个学生
request.session['selected_student_id'] = selected_student.student_id # 存储被点名学生的ID到session中
return redirect('confirm_roll_call') # 跳转到确认点名页面
return JsonResponse({"message": "点名成功", "student_id": selected_student.student_id, "student_name": selected_student.name})
return render(request, 'roll_call.html', {'selected_student': selected_student}) # 渲染点名页面
# 确认点名的视图
# def confirm_roll_call(request):
# # 从 session 中获取被点名的学生
@ -103,6 +324,52 @@ def roll_call(request):
# return redirect('roll_call') # 返回点名页面,进行下一轮点名
#
# return render(request, 'confirm_roll_call.html', {'student': student}) # 渲染确认点名页面
# def confirm_roll_call(request):
# student_id = request.session.get('selected_student_id')
# student = get_object_or_404(Student, student_id=student_id)
# protection_awarded = False # 初始化保护权标志
#
# if request.method == 'POST':
# # 增加学生的被点名次数
# student.called_count += 1
#
# # 检查学生是否有“保护权”
# if student.called_count % 3 == 0:
# # 如果被点名次数是3的倍数赋予保护权自动加2分
# student.score += 2
# protection_awarded = True # 设置保护权标志
# print(f"Student {student.name} ({student.student_id})获得保护权自动加2分")
# else:
# # 学生是否到课
# if 'attended' in request.POST: # 如果选择了到课
# student.score += 1 # 到课加1分
# student.attendance_count += 1 # 到课次数加1
#
# # 处理是否准确重复问题
# if request.POST['question_repeat'] == 'accurate':
# student.score += 0.5 # 重复问题准确加0.5分
# else:
# student.score -= 1 # 重复问题不准确扣1分
#
# # 处理回答问题的准确性0-3分
# answer_accuracy = float(request.POST.get('answer_accuracy', 0))
# student.score += answer_accuracy # 根据回答准确性加分
# else:
# student.score -= 5 # 未到课扣5分
#
# # 保存更新后的学生信息
# student.save()
# return redirect('roll_call') # 返回点名页面,进行下一轮点名
#
# return render(request, 'confirm_roll_call.html', {'student': student, 'protection_awarded': protection_awarded}) # 渲染确认点名页面
#
#
#
#
# # 积分排行榜
# def leaderboard(request):
# students = Student.objects.all().order_by('-score') # 按分数降序排列
# return render(request, 'leaderboard.html', {'students': students})
def confirm_roll_call(request):
student_id = request.session.get('selected_student_id')
student = get_object_or_404(Student, student_id=student_id)
@ -114,7 +381,6 @@ def confirm_roll_call(request):
# 检查学生是否有“保护权”
if student.called_count % 3 == 0:
# 如果被点名次数是3的倍数赋予保护权自动加2分
student.score += 2
protection_awarded = True # 设置保护权标志
print(f"Student {student.name} ({student.student_id})获得保护权自动加2分")
@ -138,14 +404,20 @@ def confirm_roll_call(request):
# 保存更新后的学生信息
student.save()
return redirect('roll_call') # 返回点名页面,进行下一轮点名
return render(request, 'confirm_roll_call.html', {'student': student, 'protection_awarded': protection_awarded}) # 渲染确认点名页面
return JsonResponse({
"message": "确认点名成功",
"student_id": student.student_id,
"student_name": student.name,
"current_score": student.score,
"protection_awarded": protection_awarded
})
return render(request, 'confirm_roll_call.html',
{'student': student, 'protection_awarded': protection_awarded}) # 渲染确认点名页面
# 积分排行榜
def leaderboard(request):
students = Student.objects.all().order_by('-score') # 按分数降序排列
return render(request, 'leaderboard.html', {'students': students})
leaderboard_data = [{"student_id": student.student_id, "name": student.name, "score": student.score} for student in students]
return JsonResponse({"leaderboard": leaderboard_data}) # 返回排行榜数据

@ -0,0 +1,354 @@
openapi: 3.0.3
info:
title: ''
version: 0.0.0
paths:
/api/schema/:
get:
operationId: api_schema_retrieve
description: |-
OpenApi3 schema for this API. Format can be selected via content negotiation.
- YAML: application/vnd.oai.openapi
- JSON: application/vnd.oai.openapi+json
parameters:
- in: query
name: format
schema:
type: string
enum:
- json
- yaml
- in: query
name: lang
schema:
type: string
enum:
- af
- ar
- ar-dz
- ast
- az
- be
- bg
- bn
- br
- bs
- ca
- cs
- cy
- da
- de
- dsb
- el
- en
- en-au
- en-gb
- eo
- es
- es-ar
- es-co
- es-mx
- es-ni
- es-ve
- et
- eu
- fa
- fi
- fr
- fy
- ga
- gd
- gl
- he
- hi
- hr
- hsb
- hu
- hy
- ia
- id
- ig
- io
- is
- it
- ja
- ka
- kab
- kk
- km
- kn
- ko
- ky
- lb
- lt
- lv
- mk
- ml
- mn
- mr
- my
- nb
- ne
- nl
- nn
- os
- pa
- pl
- pt
- pt-br
- ro
- ru
- sk
- sl
- sq
- sr
- sr-latn
- sv
- sw
- ta
- te
- tg
- th
- tk
- tr
- tt
- udm
- uk
- ur
- uz
- vi
- zh-hans
- zh-hant
tags:
- api
security:
- cookieAuth: []
- basicAuth: []
- {}
responses:
'200':
content:
application/vnd.oai.openapi:
schema:
type: object
additionalProperties: {}
application/yaml:
schema:
type: object
additionalProperties: {}
application/vnd.oai.openapi+json:
schema:
type: object
additionalProperties: {}
application/json:
schema:
type: object
additionalProperties: {}
description: ''
/polls/students/:
get:
operationId: polls_students_list
tags:
- polls
security:
- cookieAuth: []
- basicAuth: []
- {}
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Student'
description: ''
post:
operationId: polls_students_create
tags:
- polls
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Student'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Student'
multipart/form-data:
schema:
$ref: '#/components/schemas/Student'
required: true
security:
- cookieAuth: []
- basicAuth: []
- {}
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/Student'
description: ''
/polls/students/{id}/:
get:
operationId: polls_students_retrieve
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this student.
required: true
tags:
- polls
security:
- cookieAuth: []
- basicAuth: []
- {}
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Student'
description: ''
put:
operationId: polls_students_update
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this student.
required: true
tags:
- polls
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Student'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Student'
multipart/form-data:
schema:
$ref: '#/components/schemas/Student'
required: true
security:
- cookieAuth: []
- basicAuth: []
- {}
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Student'
description: ''
patch:
operationId: polls_students_partial_update
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this student.
required: true
tags:
- polls
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PatchedStudent'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/PatchedStudent'
multipart/form-data:
schema:
$ref: '#/components/schemas/PatchedStudent'
security:
- cookieAuth: []
- basicAuth: []
- {}
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/Student'
description: ''
delete:
operationId: polls_students_destroy
parameters:
- in: path
name: id
schema:
type: integer
description: A unique integer value identifying this student.
required: true
tags:
- polls
security:
- cookieAuth: []
- basicAuth: []
- {}
responses:
'204':
description: No response body
components:
schemas:
PatchedStudent:
type: object
properties:
name:
type: string
maxLength: 100
student_id:
type: string
maxLength: 100
score:
type: number
format: double
attendance_count:
type: integer
maximum: 2147483647
minimum: -2147483648
called_count:
type: integer
maximum: 2147483647
minimum: -2147483648
Student:
type: object
properties:
name:
type: string
maxLength: 100
student_id:
type: string
maxLength: 100
score:
type: number
format: double
attendance_count:
type: integer
maximum: 2147483647
minimum: -2147483648
called_count:
type: integer
maximum: 2147483647
minimum: -2147483648
required:
- name
- student_id
securitySchemes:
basicAuth:
type: http
scheme: basic
cookieAuth:
type: apiKey
in: cookie
name: sessionid
Loading…
Cancel
Save