Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: 组卷时改用bulk_create;fix: Inconsistent cache key #151

Merged
merged 4 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contest/quiz/templates/contest.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
<article class="mx-auto max-w-2xl pb-6 prose">
<form action="{% url 'quiz:contest_submit' %}" method="post">
{% csrf_token %}
{% for a in draft_response.answer_set.all %}
{% for a in answer_set.all %}
<fieldset class="my-4 p-4 sm:px-6 lg:px-8 bg-white shadow disabled:text-gray-400"
{% if draft_response.outdated %}disabled{% endif %}>
<p class="text-lg my-0">
Expand Down
35 changes: 18 additions & 17 deletions contest/quiz/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,19 @@
from django.views.generic import TemplateView

from .constants import constants
from .models import Choice, DraftResponse, Question
from .models import Choice, DraftAnswer, DraftResponse, Question
from .util import is_open, is_student, is_student_taking_contest, pass_or_forbid, student_only

if TYPE_CHECKING:
from typing import Any, Literal

from django.contrib.auth.models import AnonymousUser

from .models import DraftAnswer, Student, User
from .models import Student, User
from .util import AuthenticatedHttpRequest


def continue_or_finalize(student_: Student) -> bool:
def continue_or_finalize(draft_response: DraftResponse) -> bool:
"""自动提交

若草稿已超期,则定稿,否则什么也不做。
Expand All @@ -47,13 +47,9 @@ def continue_or_finalize(student_: Student) -> bool:
https://docs.djangoproject.com/en/4.2/ref/models/instances/#django.db.models.Model.delete
https://docs.djangoproject.com/en/4.2/ref/models/instances/#refreshing-objects-from-database
"""
draft_response: DraftResponse = student_.draft_response

if draft_response.outdated():
# 提交之前的草稿
cache_key = f"{student_.user}_json"
# 从 Redis 获取现有的答案缓存
cached_answers = cache.get(cache_key, {})
cached_answers = cache.get(f"{draft_response.id}_json", {})

if cached_answers:
for question_id, choice_id in cached_answers.items():
Expand All @@ -77,16 +73,18 @@ def continue_or_finalize(student_: Student) -> bool:

answer.save()

cache.delete(f"{student_.user}_json")
cache.delete(f"{student_.user}_ddl")
cache.delete(f"{draft_response.id}_json")
cache.delete(f"{draft_response.id}_ddl")

# 提交之前的草稿

# 1. Convert from draft
response, answers = student_.draft_response.finalize(submit_at=timezone.now())
response, answers = draft_response.finalize(submit_at=timezone.now())

# 2. Save
response.save()
response.answer_set.bulk_create(answers)
student_.draft_response.delete()
draft_response.delete()

return True

Expand All @@ -103,7 +101,7 @@ def manage_status(
if not hasattr(student, "draft_response"):
return "not taking"
else:
finalized = continue_or_finalize(student)
finalized = continue_or_finalize(student.draft_response)
if finalized:
return "deadline passed"
else:
Expand Down Expand Up @@ -222,16 +220,19 @@ def contest(request: AuthenticatedHttpRequest) -> HttpResponse:

# 保存
draft_response.save()
for q in questions:
draft_response.answer_set.create(
question=q,
)
draft_response.answer_set.bulk_create(
[DraftAnswer(question=q, response=draft_response) for q in questions]
)

return render(
request,
"contest.html",
{
"draft_response": draft_response,
# 为渲染模板预先从数据库查询相关内容
"answer_set": draft_response.answer_set.select_related(
"question"
).prefetch_related("question__choice_set"),
"constants": constants,
},
)
Expand Down