90 lines
3.3 KiB
Python
90 lines
3.3 KiB
Python
from django.db import models
|
|
from django.utils import timezone
|
|
|
|
from .models import Submission
|
|
from utils.api import serializers
|
|
from utils.serializers import LanguageNameChoiceField
|
|
from problemset.models import ProblemSetProgress
|
|
|
|
|
|
class CreateSubmissionSerializer(serializers.Serializer):
|
|
problem_id = serializers.IntegerField()
|
|
language = LanguageNameChoiceField()
|
|
code = serializers.CharField(max_length=1024 * 1024)
|
|
contest_id = serializers.IntegerField(required=False)
|
|
problemset_id = serializers.IntegerField(required=False)
|
|
captcha = serializers.CharField(required=False)
|
|
|
|
|
|
class ShareSubmissionSerializer(serializers.Serializer):
|
|
id = serializers.CharField()
|
|
shared = serializers.BooleanField()
|
|
|
|
|
|
class SubmissionModelSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
model = Submission
|
|
fields = "__all__"
|
|
|
|
|
|
# 不显示submission info的serializer, 用于ACM rule_type
|
|
class SubmissionSafeModelSerializer(serializers.ModelSerializer):
|
|
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
|
|
|
|
class Meta:
|
|
model = Submission
|
|
exclude = ("info", "contest", "ip")
|
|
|
|
|
|
class SubmissionListSerializer(serializers.ModelSerializer):
|
|
problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")
|
|
problem_title = serializers.CharField(source="problem.title")
|
|
show_link = serializers.SerializerMethodField()
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.user = kwargs.pop("user", None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
class Meta:
|
|
model = Submission
|
|
exclude = ("info", "contest", "code", "ip")
|
|
|
|
def get_show_link(self, obj):
|
|
# 没传user或为匿名user
|
|
if self.user is None or not self.user.is_authenticated:
|
|
return False
|
|
if not obj.check_user_permission(self.user):
|
|
return False
|
|
# 题单防作弊:用户加入了包含该题目的 active 题单时,隐藏加入前的提交链接
|
|
# 如果该题目已在题单中做出来了,则恢复显示
|
|
if obj.user_id == self.user.id and self.user.is_regular_user():
|
|
progress = self._get_problemset_progress(obj.problem_id)
|
|
if (
|
|
progress
|
|
and obj.create_time < progress.join_time
|
|
and str(obj.problem_id) not in progress.progress_detail
|
|
):
|
|
return False
|
|
return True
|
|
|
|
def _get_problemset_progress(self, problem_id):
|
|
"""查询用户是否加入了包含该题目的 active 题单,带缓存避免 N+1"""
|
|
if not hasattr(self, "_problemset_progress_cache"):
|
|
self._problemset_progress_cache = {}
|
|
if problem_id not in self._problemset_progress_cache:
|
|
self._problemset_progress_cache[problem_id] = (
|
|
ProblemSetProgress.objects.filter(
|
|
user=self.user,
|
|
problemset__status="active",
|
|
problemset__problemsetproblem__problem_id=problem_id,
|
|
)
|
|
.filter(
|
|
models.Q(problemset__end_time__isnull=True)
|
|
| models.Q(problemset__end_time__gt=timezone.now())
|
|
)
|
|
.only("join_time", "progress_detail")
|
|
.first()
|
|
)
|
|
return self._problemset_progress_cache[problem_id]
|