302 lines
10 KiB
Python
302 lines
10 KiB
Python
import uuid
|
||
from django.core.files import File
|
||
from django.http import JsonResponse, Http404, HttpResponse
|
||
from django.shortcuts import render, redirect
|
||
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
|
||
from .form import RegisterForm, LoginForm, CreateForm, AnswerForm
|
||
from .models import CyberUser, Question, Choice
|
||
from django.contrib.auth import authenticate, login, logout
|
||
from django.contrib.auth.decorators import login_required
|
||
from PIL import Image
|
||
from io import BytesIO
|
||
|
||
|
||
def compress_image(file_obj, max_size_bytes=1 * 1024 * 1024):
|
||
# 从文件对象读取数据并创建Image对象
|
||
img = Image.open(file_obj)
|
||
|
||
# 创建一个BytesIO对象来保存压缩后的WebP数据
|
||
output_buffer = BytesIO()
|
||
|
||
quality = 85
|
||
|
||
while True:
|
||
try:
|
||
img.save(output_buffer, 'webp', quality=quality)
|
||
except Exception as e:
|
||
print(f"Error saving image as WebP: {e}")
|
||
return None
|
||
|
||
output_buffer.seek(0)
|
||
new_size = len(output_buffer.read())
|
||
|
||
# 如果新的大小小于或等于5MB,则退出循环
|
||
if new_size <= max_size_bytes:
|
||
break
|
||
|
||
# 如果新的大小大于5MB,降低质量并重试
|
||
quality -= 5
|
||
if quality < 1:
|
||
print("Unable to compress the image to 5MB or less.")
|
||
return None
|
||
output_buffer.seek(0)
|
||
return output_buffer
|
||
|
||
|
||
def home(request):
|
||
content = {'user': request.user}
|
||
return render(request, 'home.html', content)
|
||
|
||
|
||
def about(request):
|
||
return HttpResponse("尚未完成")
|
||
|
||
|
||
@login_required(login_url='/exam/login')
|
||
def history(request):
|
||
page_size = 10
|
||
user = request.user
|
||
questions = Question.objects.filter(choice__user=user)
|
||
paginator = Paginator(questions, page_size)
|
||
page = request.GET.get('page', 1)
|
||
try:
|
||
# 尝试获取当前页的记录
|
||
question = paginator.page(page)
|
||
except PageNotAnInteger:
|
||
question = paginator.page(1)
|
||
except EmptyPage:
|
||
question = paginator.page(paginator.num_pages)
|
||
context = {'questions': question, 'page': paginator.page(page), 'paginator': paginator}
|
||
return render(request, 'history.html', context)
|
||
|
||
|
||
@login_required(login_url='/exam/login')
|
||
def history_detail(request):
|
||
questionID = request.GET.get('question')
|
||
user = request.user
|
||
if questionID:
|
||
question = Question.objects.get(uid=questionID)
|
||
if question is None:
|
||
return Http404
|
||
choice = Choice.objects.get(question=question,user=user)
|
||
if choice is None:
|
||
return Http404
|
||
context = {
|
||
'question': question,
|
||
'choice': choice,
|
||
'user': user,
|
||
'forward_url': request.META.get('HTTP_REFERER', '/'),
|
||
}
|
||
return render(request, 'history_detail.html', context)
|
||
else:
|
||
return Http404
|
||
|
||
|
||
def register(request):
|
||
if request.method == 'GET':
|
||
if request.user.is_active:
|
||
return redirect("/exam/")
|
||
return render(request, 'register.html', {'form': RegisterForm()})
|
||
elif request.method == 'POST':
|
||
if request.user.is_active:
|
||
return JsonResponse({
|
||
'code': 200,
|
||
'message': '已经登陆',
|
||
'data': 'failed',
|
||
})
|
||
form = RegisterForm(request.POST)
|
||
if form.is_valid():
|
||
username = form.cleaned_data['username']
|
||
nickname = form.cleaned_data['nickname']
|
||
password = form.cleaned_data['password1']
|
||
email = form.cleaned_data['email']
|
||
username_exist = CyberUser.objects.filter(username=username).exists()
|
||
if username_exist:
|
||
return JsonResponse({"code": 400,
|
||
"message": "验证失败",
|
||
"data": {"username": "",
|
||
"password1": "",
|
||
"password2": "",
|
||
"email": "",
|
||
},
|
||
})
|
||
CyberUser.objects.create_user(
|
||
username=username,
|
||
nickname=nickname,
|
||
password=password,
|
||
email=email,
|
||
)
|
||
return JsonResponse({"code": 200,
|
||
"message": "验证通过,已注册",
|
||
"data": {"username": "",
|
||
"password1": "",
|
||
"password2": "",
|
||
"email": "",
|
||
},
|
||
})
|
||
else:
|
||
return JsonResponse({"code": 400, "message": "验证失败", "data": {"username": form.errors.get("username"),
|
||
"password1": form.errors.get("password1"),
|
||
"password2": form.errors.get("password2"),
|
||
"email": form.errors.get("email"),
|
||
"nickname": form.errors.get("nickname")}})
|
||
else:
|
||
raise Http404
|
||
|
||
|
||
def login_view(request):
|
||
if request.method == 'GET':
|
||
if request.user.is_active:
|
||
return redirect("/exam/")
|
||
return render(request, 'login.html', {'form': LoginForm()})
|
||
elif request.method == 'POST':
|
||
if request.user.is_active:
|
||
return JsonResponse(
|
||
{
|
||
'code': 200,
|
||
'message': '已经登陆',
|
||
'data': 'abort',
|
||
}
|
||
)
|
||
form = LoginForm(request.POST)
|
||
if form.is_valid():
|
||
username = form.cleaned_data['username']
|
||
password = form.cleaned_data['password']
|
||
user = authenticate(request, username=username, password=password)
|
||
if user and user.is_active:
|
||
login(request, user)
|
||
request.session['username'] = username
|
||
request.session.set_expiry(1800)
|
||
return JsonResponse(
|
||
{
|
||
"code": 200,
|
||
"message": '登陆成功',
|
||
"data": username,
|
||
}
|
||
)
|
||
elif user and user.is_active:
|
||
return JsonResponse(
|
||
{
|
||
"code": 400,
|
||
"message": "用户状态错误,请联系管理员修正",
|
||
"data": "user is not active",
|
||
}
|
||
)
|
||
else:
|
||
return JsonResponse(
|
||
{
|
||
"code": 400,
|
||
"message": "用户名或密码错误",
|
||
"data": None,
|
||
}
|
||
)
|
||
else:
|
||
return JsonResponse(
|
||
{
|
||
"code": 400,
|
||
"message": "验证失败,用户名或密码格式错误",
|
||
"data": form.errors.get(),
|
||
}
|
||
)
|
||
else:
|
||
raise Http404
|
||
|
||
|
||
def logout_view(request):
|
||
logout(request)
|
||
return redirect('/exam/login')
|
||
|
||
|
||
@login_required(login_url='/exam/login')
|
||
def create_question(request):
|
||
if request.method == 'GET':
|
||
return render(request, 'create.html', {'form': CreateForm})
|
||
elif request.method == 'POST':
|
||
form = CreateForm(request.POST, request.FILES)
|
||
if form.is_valid():
|
||
text = form.cleaned_data['text']
|
||
image = form.cleaned_data['image']
|
||
a = form.cleaned_data['a']
|
||
b = form.cleaned_data['b']
|
||
c = form.cleaned_data['c']
|
||
d = form.cleaned_data['d']
|
||
answer = form.cleaned_data['answer']
|
||
new_question = Question(
|
||
question_text=text,
|
||
choice_a=a,
|
||
choice_b=b,
|
||
choice_c=c,
|
||
choice_d=d,
|
||
answer=answer,
|
||
)
|
||
if image:
|
||
image = compress_image(image)
|
||
new_question.image = File(image, name=f'{str(uuid.uuid4())}.webp')
|
||
new_question.save()
|
||
return JsonResponse(
|
||
{
|
||
'code': 200,
|
||
'message': 'success',
|
||
'data': '',
|
||
}
|
||
)
|
||
else:
|
||
return JsonResponse(
|
||
{
|
||
'code': 400,
|
||
'message': '参数不正确',
|
||
'data': form.errors
|
||
}
|
||
)
|
||
|
||
|
||
@login_required(login_url='/exam/login')
|
||
def get_question(request):
|
||
user = request.user
|
||
question = Question.objects.exclude(choice__user=user).order_by('?').first()
|
||
return render(request, "question.html", {'question': question, 'form': AnswerForm, 'user': request.user})
|
||
|
||
|
||
@login_required(login_url='/exam/login')
|
||
def answer(request):
|
||
if request.method == 'POST':
|
||
form = AnswerForm(request.POST)
|
||
if form.is_valid():
|
||
user = request.user
|
||
user_ans = form.cleaned_data['answer']
|
||
questionID = form.cleaned_data['questionID']
|
||
question = Question.objects.get(uid=questionID)
|
||
if Choice.objects.filter(user=user, question=question).exists():
|
||
return JsonResponse(
|
||
{
|
||
'code': 200,
|
||
'message': '该问题已经回答过了',
|
||
'data': '',
|
||
}
|
||
)
|
||
choice = Choice(user=user, question=question, choice=user_ans)
|
||
choice.save()
|
||
if user_ans == question.answer:
|
||
user.score = user.score + 1
|
||
user.save()
|
||
return JsonResponse(
|
||
{
|
||
'code': 200,
|
||
'message': 'success',
|
||
'data': {
|
||
'correction': user_ans == question.answer,
|
||
'answer': question.answer,
|
||
},
|
||
}
|
||
)
|
||
else:
|
||
return JsonResponse(
|
||
{
|
||
'code': 400,
|
||
'message': '参数错误',
|
||
'data': '表单不可用',
|
||
}
|
||
)
|
||
else:
|
||
return Http404
|