update for django6
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# Generated by Django 6.0.4 on 2026-05-09 11:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0004_alter_user_admin_type_alter_user_problem_permission'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='is_disabled',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='open_api',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='session_keys',
|
||||
field=models.JSONField(db_default=models.Value([]), default=list),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='user',
|
||||
name='two_factor_auth',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='accepted_number',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='acm_problems_status',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='oi_problems_status',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='submission_number',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='userprofile',
|
||||
name='total_score',
|
||||
field=models.BigIntegerField(db_default=0, default=0),
|
||||
),
|
||||
]
|
||||
@@ -36,13 +36,13 @@ class User(AbstractBaseUser):
|
||||
reset_password_token_expire_time = models.DateTimeField(null=True)
|
||||
# SSO auth token
|
||||
auth_token = models.TextField(null=True)
|
||||
two_factor_auth = models.BooleanField(default=False)
|
||||
two_factor_auth = models.BooleanField(default=False, db_default=False)
|
||||
tfa_token = models.TextField(null=True)
|
||||
session_keys = JSONField(default=list)
|
||||
session_keys = JSONField(default=list, db_default=models.Value([]))
|
||||
# open api key
|
||||
open_api = models.BooleanField(default=False)
|
||||
open_api = models.BooleanField(default=False, db_default=False)
|
||||
open_api_appkey = models.TextField(null=True)
|
||||
is_disabled = models.BooleanField(default=False)
|
||||
is_disabled = models.BooleanField(default=False, db_default=False)
|
||||
raw_password = models.CharField(max_length=20, null=True, blank=True, verbose_name="明文密码")
|
||||
|
||||
USERNAME_FIELD = "username"
|
||||
@@ -93,9 +93,9 @@ class UserProfile(models.Model):
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
acm_problems_status = JSONField(default=dict)
|
||||
acm_problems_status = JSONField(default=dict, db_default=models.Value({}))
|
||||
# like acm_problems_status, merely add "score" field
|
||||
oi_problems_status = JSONField(default=dict)
|
||||
oi_problems_status = JSONField(default=dict, db_default=models.Value({}))
|
||||
|
||||
real_name = models.TextField(null=True)
|
||||
avatar = models.TextField(default=f"{settings.AVATAR_URI_PREFIX}/default.png")
|
||||
@@ -106,24 +106,24 @@ class UserProfile(models.Model):
|
||||
major = models.TextField(null=True)
|
||||
language = models.TextField(null=True)
|
||||
# for ACM
|
||||
accepted_number = models.IntegerField(default=0)
|
||||
accepted_number = models.IntegerField(default=0, db_default=0)
|
||||
# for OI
|
||||
total_score = models.BigIntegerField(default=0)
|
||||
submission_number = models.IntegerField(default=0)
|
||||
total_score = models.BigIntegerField(default=0, db_default=0)
|
||||
submission_number = models.IntegerField(default=0, db_default=0)
|
||||
|
||||
def add_accepted_problem_number(self):
|
||||
self.accepted_number = models.F("accepted_number") + 1
|
||||
self.save()
|
||||
self.save(update_fields=["accepted_number"])
|
||||
|
||||
def add_submission_number(self):
|
||||
self.submission_number = models.F("submission_number") + 1
|
||||
self.save()
|
||||
self.save(update_fields=["submission_number"])
|
||||
|
||||
# 计算总分时, 应先减掉上次该题所得分数, 然后再加上本次所得分数
|
||||
def add_score(self, this_time_score, last_time_score=None):
|
||||
last_time_score = last_time_score or 0
|
||||
self.total_score = models.F("total_score") - last_time_score + this_time_score
|
||||
self.save()
|
||||
self.save(update_fields=["total_score"])
|
||||
|
||||
class Meta:
|
||||
db_table = "user_profile"
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# Generated by Django 6.0.4 on 2026-05-09 11:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('contest', '0004_alter_acmcontestrank_unique_together_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='acmcontestrank',
|
||||
name='accepted_number',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='acmcontestrank',
|
||||
name='submission_info',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='acmcontestrank',
|
||||
name='submission_number',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='acmcontestrank',
|
||||
name='total_time',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='oicontestrank',
|
||||
name='submission_info',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='oicontestrank',
|
||||
name='submission_number',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='oicontestrank',
|
||||
name='total_score',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
]
|
||||
@@ -55,19 +55,19 @@ class Contest(models.Model):
|
||||
class AbstractContestRank(models.Model):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
contest = models.ForeignKey(Contest, on_delete=models.CASCADE)
|
||||
submission_number = models.IntegerField(default=0)
|
||||
submission_number = models.IntegerField(default=0, db_default=0)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
|
||||
class ACMContestRank(AbstractContestRank):
|
||||
accepted_number = models.IntegerField(default=0)
|
||||
accepted_number = models.IntegerField(default=0, db_default=0)
|
||||
# total_time is only for ACM contest, total_time = ac time + none-ac times * 20 * 60
|
||||
total_time = models.IntegerField(default=0)
|
||||
total_time = models.IntegerField(default=0, db_default=0)
|
||||
# {"23": {"is_ac": True, "ac_time": 8999, "error_number": 2, "is_first_ac": True}}
|
||||
# key is problem id
|
||||
submission_info = JSONField(default=dict)
|
||||
submission_info = JSONField(default=dict, db_default=models.Value({}))
|
||||
|
||||
class Meta:
|
||||
db_table = "acm_contest_rank"
|
||||
@@ -81,10 +81,10 @@ class ACMContestRank(AbstractContestRank):
|
||||
|
||||
|
||||
class OIContestRank(AbstractContestRank):
|
||||
total_score = models.IntegerField(default=0)
|
||||
total_score = models.IntegerField(default=0, db_default=0)
|
||||
# {"23": 333}
|
||||
# key is problem id, value is current score
|
||||
submission_info = JSONField(default=dict)
|
||||
submission_info = JSONField(default=dict, db_default=models.Value({}))
|
||||
|
||||
class Meta:
|
||||
db_table = "oi_contest_rank"
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import hashlib
|
||||
import json
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
from urllib.parse import urljoin
|
||||
|
||||
import requests
|
||||
from django.db import IntegrityError, transaction
|
||||
from django.db.models import F
|
||||
from django.utils import timezone
|
||||
|
||||
from account.models import User
|
||||
from conf.models import JudgeServer
|
||||
@@ -38,14 +40,23 @@ class ChooseJudgeServer:
|
||||
|
||||
def __enter__(self) -> [JudgeServer, None]:
|
||||
with transaction.atomic():
|
||||
servers = JudgeServer.objects.select_for_update().filter(is_disabled=False).order_by("task_number")
|
||||
servers = [s for s in servers if s.status == "normal"]
|
||||
for server in servers:
|
||||
if server.task_number <= server.cpu_core * 2:
|
||||
server.task_number = F("task_number") + 1
|
||||
server.save(update_fields=["task_number"])
|
||||
self.server = server
|
||||
return server
|
||||
cutoff = timezone.now() - timedelta(seconds=6)
|
||||
server = (
|
||||
JudgeServer.objects
|
||||
.select_for_update(skip_locked=True)
|
||||
.filter(
|
||||
is_disabled=False,
|
||||
last_heartbeat__gte=cutoff,
|
||||
task_number__lte=F("cpu_core") * 2,
|
||||
)
|
||||
.order_by("task_number")
|
||||
.first()
|
||||
)
|
||||
if server:
|
||||
server.task_number = F("task_number") + 1
|
||||
server.save(update_fields=["task_number"])
|
||||
self.server = server
|
||||
return server
|
||||
return None
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
@@ -196,8 +207,8 @@ class JudgeDispatcher(DispatcherBase):
|
||||
self.submission.result = error_test_case[0]["result"]
|
||||
else:
|
||||
self.submission.result = JudgeStatus.PARTIALLY_ACCEPTED
|
||||
self.submission.save()
|
||||
|
||||
self.submission.save(update_fields=["result", "info", "statistic_info"])
|
||||
|
||||
# 推送判题完成状态
|
||||
try:
|
||||
push_submission_update(
|
||||
@@ -241,7 +252,7 @@ class JudgeDispatcher(DispatcherBase):
|
||||
# update problem status
|
||||
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
|
||||
if self.last_result != JudgeStatus.ACCEPTED and self.submission.result == JudgeStatus.ACCEPTED:
|
||||
problem.accepted_number += 1
|
||||
problem.accepted_number = F("accepted_number") + 1
|
||||
problem_info = problem.statistic_info
|
||||
problem_info[self.last_result] = problem_info.get(self.last_result, 1) - 1
|
||||
problem_info[result] = problem_info.get(result, 0) + 1
|
||||
@@ -277,9 +288,9 @@ class JudgeDispatcher(DispatcherBase):
|
||||
with transaction.atomic():
|
||||
# update problem status
|
||||
problem = Problem.objects.select_for_update().get(contest_id=self.contest_id, id=self.problem.id)
|
||||
problem.submission_number += 1
|
||||
problem.submission_number = F("submission_number") + 1
|
||||
if self.submission.result == JudgeStatus.ACCEPTED:
|
||||
problem.accepted_number += 1
|
||||
problem.accepted_number = F("accepted_number") + 1
|
||||
problem_info = problem.statistic_info
|
||||
problem_info[result] = problem_info.get(result, 0) + 1
|
||||
problem.save(update_fields=["accepted_number", "submission_number", "statistic_info"])
|
||||
@@ -287,7 +298,7 @@ class JudgeDispatcher(DispatcherBase):
|
||||
# update_userprofile
|
||||
user = User.objects.select_for_update().get(id=self.submission.user_id)
|
||||
user_profile = user.userprofile
|
||||
user_profile.submission_number += 1
|
||||
user_profile.submission_number = F("submission_number") + 1
|
||||
if problem.rule_type == ProblemRuleType.ACM:
|
||||
acm_problems_status = user_profile.acm_problems_status.get("problems", {})
|
||||
if problem_id not in acm_problems_status:
|
||||
@@ -356,9 +367,9 @@ class JudgeDispatcher(DispatcherBase):
|
||||
result = str(self.submission.result)
|
||||
problem_info = problem.statistic_info
|
||||
problem_info[result] = problem_info.get(result, 0) + 1
|
||||
problem.submission_number += 1
|
||||
problem.submission_number = F("submission_number") + 1
|
||||
if self.submission.result == JudgeStatus.ACCEPTED:
|
||||
problem.accepted_number += 1
|
||||
problem.accepted_number = F("accepted_number") + 1
|
||||
problem.save(update_fields=["submission_number", "accepted_number", "statistic_info"])
|
||||
|
||||
def update_contest_rank(self):
|
||||
@@ -422,7 +433,7 @@ class JudgeDispatcher(DispatcherBase):
|
||||
elif self.submission.result != JudgeStatus.COMPILE_ERROR:
|
||||
info["error_number"] = 1
|
||||
rank.submission_info[str(self.submission.problem_id)] = info
|
||||
rank.save()
|
||||
rank.save(update_fields=["submission_info", "total_time", "accepted_number", "submission_number"])
|
||||
|
||||
def _update_oi_contest_rank(self, rank):
|
||||
problem_id = str(self.submission.problem_id)
|
||||
@@ -433,4 +444,4 @@ class JudgeDispatcher(DispatcherBase):
|
||||
else:
|
||||
rank.total_score = rank.total_score + current_score
|
||||
rank.submission_info[problem_id] = current_score
|
||||
rank.save()
|
||||
rank.save(update_fields=["submission_info", "total_score", "submission_number"])
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
# Generated by Django 6.0.4 on 2026-05-09 11:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('problem', '0008_alter_problem_unique_together_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='accepted_number',
|
||||
field=models.BigIntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='allow_flowchart',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='flowchart_data',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='is_public',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='share_submission',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='show_flowchart',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='statistic_info',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='submission_number',
|
||||
field=models.BigIntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='total_score',
|
||||
field=models.IntegerField(db_default=0, default=0),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='problem',
|
||||
name='visible',
|
||||
field=models.BooleanField(db_default=True, default=True),
|
||||
),
|
||||
]
|
||||
@@ -36,7 +36,7 @@ class Problem(models.Model):
|
||||
_id = models.TextField(db_index=True)
|
||||
contest = models.ForeignKey(Contest, null=True, on_delete=models.CASCADE)
|
||||
# for contest problem
|
||||
is_public = models.BooleanField(default=False)
|
||||
is_public = models.BooleanField(default=False, db_default=False)
|
||||
title = models.TextField()
|
||||
# HTML
|
||||
description = RichTextField()
|
||||
@@ -61,7 +61,7 @@ class Problem(models.Model):
|
||||
# io mode
|
||||
io_mode = models.JSONField(default=_default_io_mode)
|
||||
rule_type = models.TextField(choices=ProblemRuleType.choices)
|
||||
visible = models.BooleanField(default=True)
|
||||
visible = models.BooleanField(default=True, db_default=True)
|
||||
difficulty = models.TextField(choices=Difficulty.choices)
|
||||
tags = models.ManyToManyField(ProblemTag)
|
||||
source = models.TextField(null=True)
|
||||
@@ -69,19 +69,19 @@ class Problem(models.Model):
|
||||
# [{language: "python", code: "..."}]
|
||||
answers = models.JSONField(null=True)
|
||||
# for OI mode
|
||||
total_score = models.IntegerField(default=0)
|
||||
submission_number = models.BigIntegerField(default=0)
|
||||
accepted_number = models.BigIntegerField(default=0)
|
||||
total_score = models.IntegerField(default=0, db_default=0)
|
||||
submission_number = models.BigIntegerField(default=0, db_default=0)
|
||||
accepted_number = models.BigIntegerField(default=0, db_default=0)
|
||||
# {JudgeStatus.ACCEPTED: 3, JudgeStatus.WRONG_ANSWER: 11}, the number means count
|
||||
statistic_info = models.JSONField(default=dict)
|
||||
share_submission = models.BooleanField(default=False)
|
||||
statistic_info = models.JSONField(default=dict, db_default=models.Value({}))
|
||||
share_submission = models.BooleanField(default=False, db_default=False)
|
||||
|
||||
# 流程图相关字段
|
||||
allow_flowchart = models.BooleanField(default=False) # 是否允许/需要提交流程图
|
||||
mermaid_code = models.TextField(null=True, blank=True) # 流程图答案(Mermaid代码)
|
||||
flowchart_data = models.JSONField(default=dict) # 流程图答案元数据(JSON格式)
|
||||
flowchart_hint = models.TextField(null=True, blank=True) # 流程图提示信息
|
||||
show_flowchart = models.BooleanField(default=False) # 是否显示流程图答案数据,如果True,这样就不需要提交流程图了,说明就是给学生看的
|
||||
allow_flowchart = models.BooleanField(default=False, db_default=False)
|
||||
mermaid_code = models.TextField(null=True, blank=True)
|
||||
flowchart_data = models.JSONField(default=dict, db_default=models.Value({}))
|
||||
flowchart_hint = models.TextField(null=True, blank=True)
|
||||
show_flowchart = models.BooleanField(default=False, db_default=False)
|
||||
|
||||
class Meta:
|
||||
db_table = "problem"
|
||||
|
||||
@@ -118,11 +118,11 @@ class ProblemSetBadge(models.Model):
|
||||
|
||||
def _is_eligible(self, progress):
|
||||
"""判断用户进度是否满足该徽章条件(纯逻辑,不查数据库)"""
|
||||
if self.condition_type == "all_problems":
|
||||
if self.condition_type == BadgeConditionType.ALL_PROBLEMS:
|
||||
return progress.completed_problems_count == progress.total_problems_count
|
||||
if self.condition_type == "problem_count":
|
||||
if self.condition_type == BadgeConditionType.PROBLEM_COUNT:
|
||||
return progress.completed_problems_count >= self.condition_value
|
||||
if self.condition_type == "score":
|
||||
if self.condition_type == BadgeConditionType.SCORE:
|
||||
return progress.total_score >= self.condition_value
|
||||
return False
|
||||
|
||||
|
||||
@@ -4,10 +4,12 @@ from django.utils import timezone
|
||||
from account.models import User
|
||||
from problem.models import Problem
|
||||
from problemset.models import (
|
||||
BadgeConditionType,
|
||||
ProblemSet,
|
||||
ProblemSetBadge,
|
||||
ProblemSetProblem,
|
||||
ProblemSetProgress,
|
||||
ProblemSetStatus,
|
||||
ProblemSetSubmission,
|
||||
UserBadge,
|
||||
)
|
||||
@@ -31,7 +33,7 @@ class ProblemSetAPI(APIView):
|
||||
def get(self, request):
|
||||
"""获取题单列表"""
|
||||
# 预加载创建者信息
|
||||
problem_sets = ProblemSet.objects.filter(visible=True).exclude(status="draft").select_related("created_by")
|
||||
problem_sets = ProblemSet.objects.filter(visible=True).exclude(status=ProblemSetStatus.DRAFT).select_related("created_by")
|
||||
|
||||
# 使用annotate在查询时计算题目数量,避免N+1查询
|
||||
problem_sets = problem_sets.annotate(problems_count=Count("problemsetproblem", distinct=True))
|
||||
@@ -90,7 +92,7 @@ class ProblemSetDetailAPI(APIView):
|
||||
def get(self, request, problem_set_id):
|
||||
"""获取题单详情"""
|
||||
try:
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status=ProblemSetStatus.DRAFT).get()
|
||||
except ProblemSet.DoesNotExist:
|
||||
return self.error("题单不存在")
|
||||
|
||||
@@ -104,7 +106,7 @@ class ProblemSetProblemAPI(APIView):
|
||||
def get(self, request, problem_set_id):
|
||||
"""获取题单中的题目列表"""
|
||||
try:
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status=ProblemSetStatus.DRAFT).get()
|
||||
except ProblemSet.DoesNotExist:
|
||||
return self.error("题单不存在")
|
||||
|
||||
@@ -128,7 +130,7 @@ class ProblemSetProgressAPI(APIView):
|
||||
"""加入题单"""
|
||||
data = request.data
|
||||
try:
|
||||
problem_set = ProblemSet.objects.filter(id=data["problemset_id"], visible=True).exclude(status="draft").get()
|
||||
problem_set = ProblemSet.objects.filter(id=data["problemset_id"], visible=True).exclude(status=ProblemSetStatus.DRAFT).get()
|
||||
except ProblemSet.DoesNotExist:
|
||||
return self.error("题单不存在")
|
||||
|
||||
@@ -144,7 +146,7 @@ class ProblemSetProgressAPI(APIView):
|
||||
def get(self, request, problem_set_id):
|
||||
"""获取题单进度"""
|
||||
try:
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status=ProblemSetStatus.DRAFT).get()
|
||||
except ProblemSet.DoesNotExist:
|
||||
return self.error("题单不存在")
|
||||
|
||||
@@ -161,7 +163,7 @@ class ProblemSetProgressAPI(APIView):
|
||||
"""更新进度"""
|
||||
data = request.data
|
||||
try:
|
||||
problem_set = ProblemSet.objects.filter(id=data["problemset_id"], visible=True).exclude(status="draft").get()
|
||||
problem_set = ProblemSet.objects.filter(id=data["problemset_id"], visible=True).exclude(status=ProblemSetStatus.DRAFT).get()
|
||||
except ProblemSet.DoesNotExist:
|
||||
return self.error("题单不存在")
|
||||
|
||||
@@ -223,13 +225,13 @@ class ProblemSetProgressAPI(APIView):
|
||||
if UserBadge.objects.filter(user=progress.user, badge=badge).exists():
|
||||
continue
|
||||
|
||||
if badge.condition_type == "all_problems":
|
||||
if badge.condition_type == BadgeConditionType.ALL_PROBLEMS:
|
||||
if progress.completed_problems_count == progress.total_problems_count:
|
||||
UserBadge.objects.create(user=progress.user, badge=badge)
|
||||
elif badge.condition_type == "problem_count":
|
||||
elif badge.condition_type == BadgeConditionType.PROBLEM_COUNT:
|
||||
if progress.completed_problems_count >= badge.condition_value:
|
||||
UserBadge.objects.create(user=progress.user, badge=badge)
|
||||
elif badge.condition_type == "score":
|
||||
elif badge.condition_type == BadgeConditionType.SCORE:
|
||||
if progress.total_score >= badge.condition_value:
|
||||
UserBadge.objects.create(user=progress.user, badge=badge)
|
||||
|
||||
@@ -273,7 +275,7 @@ class ProblemSetBadgeAPI(APIView):
|
||||
def get(self, request, problem_set_id):
|
||||
"""获取题单的奖章列表"""
|
||||
try:
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status=ProblemSetStatus.DRAFT).get()
|
||||
except ProblemSet.DoesNotExist:
|
||||
return self.error("题单不存在")
|
||||
|
||||
@@ -288,7 +290,7 @@ class ProblemSetUserProgressAPI(APIView):
|
||||
def get(self, request, problem_set_id: int):
|
||||
"""获取题单的用户进度列表"""
|
||||
try:
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status=ProblemSetStatus.DRAFT).get()
|
||||
except ProblemSet.DoesNotExist:
|
||||
return self.error("题单不存在")
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Generated by Django 6.0.4 on 2026-05-09 11:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('submission', '0005_alter_submission_result'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='submission',
|
||||
name='info',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='submission',
|
||||
name='result',
|
||||
field=models.IntegerField(choices=[(-2, 'Compile Error'), (-1, 'Wrong Answer'), (0, 'Accepted'), (1, 'CPU Time Limit Exceeded'), (2, 'Real Time Limit Exceeded'), (3, 'Memory Limit Exceeded'), (4, 'Runtime Error'), (5, 'System Error'), (6, 'Pending'), (7, 'Judging'), (8, 'Partially Accepted')], db_default=6, db_index=True, default=6),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='submission',
|
||||
name='shared',
|
||||
field=models.BooleanField(db_default=False, default=False),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='submission',
|
||||
name='statistic_info',
|
||||
field=models.JSONField(db_default=models.Value({}), default=dict),
|
||||
),
|
||||
]
|
||||
@@ -29,14 +29,14 @@ class Submission(models.Model):
|
||||
user_id = models.IntegerField(db_index=True)
|
||||
username = models.TextField()
|
||||
code = models.TextField()
|
||||
result = models.IntegerField(choices=JudgeStatus.choices, db_index=True, default=JudgeStatus.PENDING)
|
||||
result = models.IntegerField(choices=JudgeStatus.choices, db_index=True, default=JudgeStatus.PENDING, db_default=JudgeStatus.PENDING)
|
||||
# 从JudgeServer返回的判题详情
|
||||
info = JSONField(default=dict)
|
||||
info = JSONField(default=dict, db_default=models.Value({}))
|
||||
language = models.TextField()
|
||||
shared = models.BooleanField(default=False)
|
||||
shared = models.BooleanField(default=False, db_default=False)
|
||||
# 存储该提交所用时间和内存值,方便提交列表显示
|
||||
# {time_cost: "", memory_cost: "", err_info: "", score: 0}
|
||||
statistic_info = JSONField(default=dict)
|
||||
statistic_info = JSONField(default=dict, db_default=models.Value({}))
|
||||
ip = models.TextField(null=True)
|
||||
|
||||
def check_user_permission(self, user, check_share=True):
|
||||
|
||||
@@ -2,7 +2,7 @@ from django.db import models
|
||||
from django.db.models import F
|
||||
from django.utils import timezone
|
||||
|
||||
from problemset.models import ProblemSetProgress
|
||||
from problemset.models import ProblemSetProgress, ProblemSetStatus
|
||||
from utils.api import serializers
|
||||
from utils.serializers import LanguageNameChoiceField
|
||||
|
||||
@@ -16,7 +16,7 @@ def bulk_fetch_problemset_progress(user, problem_ids):
|
||||
rows = (
|
||||
ProblemSetProgress.objects.filter(
|
||||
user=user,
|
||||
problemset__status="active",
|
||||
problemset__status=ProblemSetStatus.ACTIVE,
|
||||
problemset__problemsetproblem__problem_id__in=problem_ids,
|
||||
)
|
||||
.filter(
|
||||
@@ -108,7 +108,7 @@ class SubmissionListSerializer(serializers.ModelSerializer):
|
||||
self._problemset_progress_cache[problem_id] = (
|
||||
ProblemSetProgress.objects.filter(
|
||||
user=self.user,
|
||||
problemset__status="active",
|
||||
problemset__status=ProblemSetStatus.ACTIVE,
|
||||
problemset__problemsetproblem__problem_id=problem_id,
|
||||
)
|
||||
.filter(
|
||||
|
||||
Reference in New Issue
Block a user