添加submission_list 和 submission details API

This commit is contained in:
zemal 2017-07-05 21:09:14 +08:00
parent 62274224a9
commit 35f6c9c4a7
4 changed files with 65 additions and 95 deletions

View File

@ -1,5 +1,6 @@
from django.db import models from django.db import models
from jsonfield import JSONField from jsonfield import JSONField
from account.models import AdminType
from utils.shortcuts import rand_str from utils.shortcuts import rand_str
@ -33,6 +34,11 @@ class Submission(models.Model):
# 存储该提交所用时间和内存值,方便提交列表显示 # 存储该提交所用时间和内存值,方便提交列表显示
statistic_info = JSONField(default={}) statistic_info = JSONField(default={})
def check_user_permission(self, user):
return self.user_id == user.id or \
self.shared is True or \
user.admin_type == AdminType.SUPER_ADMIN
class Meta: class Meta:
db_table = "submission" db_table = "submission"

View File

@ -11,13 +11,43 @@ class CreateSubmissionSerializer(serializers.Serializer):
class SubmissionModelSerializer(serializers.ModelSerializer): class SubmissionModelSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField()
info = serializers.JSONField() info = serializers.JSONField()
statistic_info = serializers.JSONField() statistic_info = serializers.JSONField()
class Meta: class Meta:
model = Submission model = Submission
# 不显示submission info详情的serializer
class SubmissionSafeSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField()
statistic_info = serializers.JSONField()
class Meta:
model = Submission
exclude = ('info', 'contest_id')
@staticmethod
def get_username(obj):
return User.objects.get(id=obj.user_id).username
class SubmissionListSerializer(SubmissionSafeSerializer):
username = serializers.SerializerMethodField()
statistic_info = serializers.JSONField()
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_id', 'code')
def get_show_link(self, obj):
return obj.check_user_permission(self.user)
@staticmethod @staticmethod
def get_username(obj): def get_username(obj):
return User.objects.get(id=obj.user_id).username return User.objects.get(id=obj.user_id).username

View File

@ -1,7 +1,8 @@
from django.conf.urls import url from django.conf.urls import url
from ..views.oj import SubmissionAPI from ..views.oj import SubmissionAPI, SubmissionListAPI
urlpatterns = [ urlpatterns = [
url(r"^submissions/?$", SubmissionAPI.as_view(), name="submission_api"), url(r"^submission/?$", SubmissionAPI.as_view(), name="submission_api"),
url(r"^submissions/?$", SubmissionListAPI.as_view(), name="submission_list_api"),
] ]

View File

@ -1,16 +1,16 @@
from django.core.paginator import Paginator
from django_redis import get_redis_connection from django_redis import get_redis_connection
from account.decorators import login_required from account.decorators import login_required
from account.models import AdminType, User from account.models import AdminType, User
from problem.models import Problem from problem.models import Problem, ProblemRuleType
from submission.tasks import judge_task from submission.tasks import judge_task
# from judge.dispatcher import JudgeDispatcher # from judge.dispatcher import JudgeDispatcher
from utils.api import APIView, validate_serializer from utils.api import APIView, validate_serializer
from utils.shortcuts import build_query_string
from utils.throttling import TokenBucket, BucketController from utils.throttling import TokenBucket, BucketController
from ..models import Submission, JudgeStatus from ..models import Submission, JudgeStatus
from ..serializers import CreateSubmissionSerializer, SubmissionModelSerializer from ..serializers import CreateSubmissionSerializer, SubmissionModelSerializer
from ..serializers import SubmissionSafeSerializer, SubmissionListSerializer
def _submit(response, user, problem_id, language, code, contest_id=None): def _submit(response, user, problem_id, language, code, contest_id=None):
@ -53,16 +53,29 @@ class SubmissionAPI(APIView):
@login_required @login_required
def get(self, request): def get(self, request):
submission_id = request.GET.get("id") submission_id = request.GET.get("id")
if submission_id: if not submission_id:
try: return self.error("Parameter id doesn't exist.")
submission = Submission.objects.get(id=submission_id, user_id=request.user.id) try:
except Submission.DoesNotExist: submission = Submission.objects.get(id=submission_id, user_id=request.user.id)
return self.error("Submission not exist") except Submission.DoesNotExist:
return self.success(SubmissionModelSerializer(submission).data) return self.error("Submission doesn't exist.")
if not submission.check_user_permission(request.user):
return self.error("No permission for this submission.")
# check problem'rule is ACM or IO.
if Problem.objects.filter(_id=submission.problem_id,
visible=True,
rule_type=ProblemRuleType.ACM
).exists():
return self.success(SubmissionSafeSerializer(submission).data)
return self.success(SubmissionModelSerializer(submission).data)
class SubmissionListAPI(APIView):
def get(self, request):
contest_id = request.GET.get("contest_id") contest_id = request.GET.get("contest_id")
if contest_id: if contest_id:
subs = Submission.objects.filter(contest_id__isnull=False) subs = Submission.objects.filter(contest_id=contest_id)
else: else:
subs = Submission.objects.filter(contest_id__isnull=True) subs = Submission.objects.filter(contest_id__isnull=True)
@ -73,87 +86,7 @@ class SubmissionAPI(APIView):
if request.GET.get("myself"): if request.GET.get("myself"):
subs = subs.filter(user_id=request.user.id) subs = subs.filter(user_id=request.user.id)
# todo: paginate # todo: paginate
return self.success(SubmissionModelSerializer(subs, many=True).data) return self.success(SubmissionListSerializer(subs, many=True, user=request.user).data)
class SubmissionListAPI(APIView):
"""
所有提交的列表
"""
def get(self, request, **kwargs):
submission_filter = {"my": None, "user_id": None}
show_all = False
page = kwargs.get("page", 1)
user_id = request.GET.get("user_id")
if user_id and request.user.admin_type == AdminType.SUPER_ADMIN:
submission_filter["user_id"] = user_id
submissions = Submission.objects.filter(user_id=user_id, contest_id__isnull=True)
else:
show_all = True
if request.GET.get("my") == "true":
submission_filter["my"] = "true"
show_all = False
if show_all:
submissions = Submission.objects.filter(contest_id__isnull=True)
else:
submissions = Submission.objects.filter(user_id=request.user.id, contest_id__isnull=True)
submissions = submissions.values("id", "user_id", "problem_id", "result", "created_time",
"accepted_time", "language").order_by("-created_time")
language = request.GET.get("language")
if language:
submissions = submissions.filter(language=language)
submission_filter["language"] = language
result = request.GET.get("result")
if result:
# TODO 转换为数字结果
submissions = submissions.filter(result=int(result))
submission_filter["result"] = result
paginator = Paginator(submissions, 20)
try:
submissions = paginator.page(int(page))
except Exception:
return self.error("Page not exist")
# Cache
cache_result = {"problem": {}, "user": {}}
for item in submissions:
problem_id = item["problem_id"]
if problem_id not in cache_result["problem"]:
problem = Problem.objects.get(id=problem_id)
cache_result["problem"][problem_id] = problem.title
item["title"] = cache_result["problem"][problem_id]
user_id = item["user_id"]
if user_id not in cache_result["user"]:
user = User.objects.get(id=user_id)
cache_result["user"][user_id] = user
item["user"] = cache_result["user"][user_id]
if item["user_id"] == request.user.id or request.user.admin_type == AdminType.SUPER_ADMIN:
item["show_link"] = True
else:
item["show_link"] = False
previous_page = next_page = None
try:
previous_page = submissions.previous_page_number()
except Exception:
pass
try:
next_page = submissions.next_page_number()
except Exception:
pass
return self.success({"submissions": submissions.object_list, "page": int(page),
"previous_page": previous_page, "next_page": next_page,
"start_id": int(page) * 20 - 20,
"query": build_query_string(submission_filter),
"submission_filter": submission_filter,
"show_all": show_all})
def _get_submission(submission_id, user): def _get_submission(submission_id, user):
@ -192,7 +125,7 @@ class SubmissionDetailAPI(APIView):
pass pass
else: else:
problem = Problem.objects.get(id=submission.problem_id, visible=True) problem = Problem.objects.get(id=submission.problem_id, visible=True)
except (Problem.DoesNotExist, ): except (Problem.DoesNotExist,):
return self.error("Submission not exist") return self.error("Submission not exist")
if submission.result in [JudgeStatus.COMPILE_ERROR, JudgeStatus.SYSTEM_ERROR, JudgeStatus.PENDING]: if submission.result in [JudgeStatus.COMPILE_ERROR, JudgeStatus.SYSTEM_ERROR, JudgeStatus.PENDING]: