contest and contest_problems api.

add ordering for contest and submission models
This commit is contained in:
zemal 2017-07-17 21:28:06 +08:00
parent ee2f5f5dd7
commit 53d0cae8ea
13 changed files with 160 additions and 25 deletions

View File

@ -4,6 +4,8 @@ from utils.api import JSONResponse
from .models import ProblemPermission from .models import ProblemPermission
from contest.models import Contest, ContestType, ContestStatus
class BasePermissionDecorator(object): class BasePermissionDecorator(object):
def __init__(self, func): def __init__(self, func):
@ -53,3 +55,42 @@ class problem_permission_required(admin_role_required):
if self.request.user.problem_permission == ProblemPermission.NONE: if self.request.user.problem_permission == ProblemPermission.NONE:
return False return False
return True return True
def check_contest_permission(func):
"""
只供Class based view 使用检查用户是否有权进入该contest
若通过验证在view中可通过self.contest获得该contest
"""
@functools.wraps(func)
def _check_permission(*args, **kwargs):
self = args[0]
request = args[1]
user = request.user
if kwargs.get('contest_id'):
contest_id = kwargs.pop('contest_id')
else:
contest_id = request.GET.get('contest_id')
if not contest_id:
return self.error("Parameter contest_id not exist.")
try:
# use self.contest to avoid query contest again in view.
self.contest = Contest.objects.get(id=contest_id, visible=True)
except Contest.DoesNotExist:
return self.error("Contest %s doesn't exist" % contest_id)
if self.contest.contest_type == ContestType.PASSWORD_PROTECTED_CONTEST:
# Anonymous
if not user.is_authenticated():
return self.error("Please login in first.")
# creator
if request.user == self.contest.created_by:
return func(*args, **kwargs)
# password error
if ("contests" not in request.session) or (self.contest.id not in request.session["contests"]):
return self.error("Password is required.")
return func(*args, **kwargs)
return _check_permission

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2017-07-17 13:24
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('contest', '0003_auto_20170217_0820'),
]
operations = [
migrations.AlterModelOptions(
name='contest',
options={'ordering': ('create_time',)},
),
]

View File

@ -12,9 +12,9 @@ class ContestType(object):
class ContestStatus(object): class ContestStatus(object):
CONTEST_NOT_START = "Not Started" CONTEST_NOT_START = "1"
CONTEST_ENDED = "Ended" CONTEST_ENDED = "-1"
CONTEST_UNDERWAY = "Underway" CONTEST_UNDERWAY = "0"
class ContestRuleType(object): class ContestRuleType(object):
@ -58,6 +58,7 @@ class Contest(models.Model):
class Meta: class Meta:
db_table = "contest" db_table = "contest"
ordering = ("create_time",)
class ContestRank(models.Model): class ContestRank(models.Model):

View File

@ -2,6 +2,8 @@ from utils.api import DateTimeTZField, UsernameSerializer, serializers
from .models import Contest, ContestAnnouncement, ContestRuleType from .models import Contest, ContestAnnouncement, ContestRuleType
from problem.serializers import ContestProblemSerializer
class CreateConetestSeriaizer(serializers.Serializer): class CreateConetestSeriaizer(serializers.Serializer):
title = serializers.CharField(max_length=128) title = serializers.CharField(max_length=128)
@ -14,6 +16,17 @@ class CreateConetestSeriaizer(serializers.Serializer):
real_time_rank = serializers.BooleanField() real_time_rank = serializers.BooleanField()
class EditConetestSeriaizer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=128)
description = serializers.CharField()
start_time = serializers.DateTimeField()
end_time = serializers.DateTimeField()
password = serializers.CharField(allow_blank=True, allow_null=True, max_length=32)
visible = serializers.BooleanField()
real_time_rank = serializers.BooleanField()
class ContestSerializer(serializers.ModelSerializer): class ContestSerializer(serializers.ModelSerializer):
start_time = DateTimeTZField() start_time = DateTimeTZField()
end_time = DateTimeTZField() end_time = DateTimeTZField()
@ -27,16 +40,6 @@ class ContestSerializer(serializers.ModelSerializer):
model = Contest model = Contest
exclude = ('password', 'visible') exclude = ('password', 'visible')
class EditConetestSeriaizer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=128)
description = serializers.CharField()
start_time = serializers.DateTimeField()
end_time = serializers.DateTimeField()
password = serializers.CharField(allow_blank=True, allow_null=True, max_length=32)
visible = serializers.BooleanField()
real_time_rank = serializers.BooleanField()
class ContestAnnouncementSerializer(serializers.ModelSerializer): class ContestAnnouncementSerializer(serializers.ModelSerializer):
created_by = UsernameSerializer() created_by = UsernameSerializer()
@ -50,3 +53,8 @@ class CreateContestAnnouncementSerializer(serializers.Serializer):
title = serializers.CharField(max_length=128) title = serializers.CharField(max_length=128)
content = serializers.CharField() content = serializers.CharField()
contest_id = serializers.IntegerField() contest_id = serializers.IntegerField()
class ContestPasswordVerifySerializer(serializers.Serializer):
contest_id = serializers.IntegerField()
password = serializers.CharField(max_length=30, required=True)

View File

@ -1,9 +1,9 @@
from django.conf.urls import url from django.conf.urls import url
from ..views.oj import ContestAnnouncementListAPI, ContestListAPI from ..views.oj import ContestAnnouncementListAPI, ContestAPI
urlpatterns = [ urlpatterns = [
url(r"^contest/?$", ContestListAPI.as_view(), name="contest_api"), url(r"^contest/?$", ContestAPI.as_view(), name="contest_api"),
url(r"^contest/announcement/?$", ContestAnnouncementListAPI.as_view(), name="contest_announcement_api"), url(r"^contest/announcement/?$", ContestAnnouncementListAPI.as_view(), name="contest_announcement_api"),
] ]

View File

@ -1,8 +1,9 @@
from utils.api import APIView from utils.api import APIView, validate_serializer
from account.decorators import login_required
from ..models import ContestAnnouncement, Contest from ..models import ContestAnnouncement, Contest
from ..serializers import ContestAnnouncementSerializer from ..serializers import ContestAnnouncementSerializer
from ..serializers import ContestSerializer from ..serializers import ContestSerializer, ContestPasswordVerifySerializer
class ContestAnnouncementListAPI(APIView): class ContestAnnouncementListAPI(APIView):
@ -17,18 +18,39 @@ class ContestAnnouncementListAPI(APIView):
return self.success(ContestAnnouncementSerializer(data, many=True).data) return self.success(ContestAnnouncementSerializer(data, many=True).data)
class ContestListAPI(APIView): class ContestAPI(APIView):
def get(self, request): def get(self, request):
contest_id = request.GET.get("id") contest_id = request.GET.get("contest_id")
if contest_id: if contest_id:
try: try:
contest = Contest.objects.get(id=contest_id, visible=True) contest = Contest.objects.get(id=contest_id, visible=True)
return self.success(ContestSerializer(contest).data) return self.success(ContestSerializer(contest).data)
except Contest.DoesNotExist: except Contest.DoesNotExist:
return self.error("Contest Doesn't exist.") return self.error("Contest doesn't exist.")
contests = Contest.objects.filter(visible=True) contests = Contest.objects.filter(visible=True)
keyword = request.GET.get("keyword") keyword = request.GET.get("keyword")
if keyword: if keyword:
contests = contests.filter(title__contains=keyword) contests = contests.filter(title__contains=keyword)
return self.success(self.paginate_data(request, contests, ContestSerializer)) return self.success(self.paginate_data(request, contests, ContestSerializer))
class ContestPasswordVerifyAPI(APIView):
@validate_serializer(ContestPasswordVerifySerializer)
@login_required
def get(self, request):
data = request.data
try:
contest = Contest.objects.get(id=data["contest_id"], visible=True, password__isnull=False)
except Contest.DoesNotExist:
return self.error("Contest %s doesn't exist." % data["contest_id"])
if contest.password != data["password"]:
return self.error("Password doesn't match.")
# password verify OK.
if "contests" not in request.session:
request.session["contests"] = []
request.session["contests"].append(int(data["contest_id"]))
# https://docs.djangoproject.com/en/dev/topics/http/sessions/#when-sessions-are-saved
request.session.modified = True
return self.success(True)

View File

@ -99,7 +99,7 @@ _java_lang_config = {
"compile_command": "/usr/bin/javac {src_path} -d {exe_dir} -encoding UTF8" "compile_command": "/usr/bin/javac {src_path} -d {exe_dir} -encoding UTF8"
}, },
"run": { "run": {
"command": "/usr/bin/java -cp {exe_dir} -Xss1M -XX:MaxPermSize=16M -XX:PermSize=8M -Xms16M -Xmx{max_memory}k " "command": "/usr/bin/java -cp {exe_dir} -Xss1M -Xms16M -Xmx{max_memory}k "
"-Djava.security.manager -Djava.security.policy==/etc/java_policy -Djava.awt.headless=true Main", "-Djava.security.manager -Djava.security.policy==/etc/java_policy -Djava.awt.headless=true Main",
"seccomp_rule": None, "seccomp_rule": None,
"env": ["MALLOC_ARENA_MAX=1"] "env": ["MALLOC_ARENA_MAX=1"]

View File

@ -4,6 +4,7 @@ from judge.languages import language_names, spj_language_names
from utils.api import DateTimeTZField, UsernameSerializer, serializers from utils.api import DateTimeTZField, UsernameSerializer, serializers
from .models import Problem, ProblemRuleType, ProblemTag from .models import Problem, ProblemRuleType, ProblemTag
from .models import ContestProblem
class TestCaseUploadForm(forms.Form): class TestCaseUploadForm(forms.Form):
@ -85,3 +86,17 @@ class ProblemSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Problem model = Problem
class ContestProblemSerializer(serializers.ModelSerializer):
samples = serializers.JSONField()
test_case_score = serializers.JSONField()
languages = serializers.JSONField()
template = serializers.JSONField()
tags = serializers.SlugRelatedField(many=True, slug_field="name", read_only=True)
create_time = DateTimeTZField()
last_update_time = DateTimeTZField()
created_by = UsernameSerializer()
class Meta:
model = ContestProblem

View File

@ -1,8 +1,9 @@
from django.conf.urls import url from django.conf.urls import url
from ..views.oj import ProblemTagAPI, ProblemAPI from ..views.oj import ProblemTagAPI, ProblemAPI, ContestProblemAPI
urlpatterns = [ urlpatterns = [
url(r"^problem/tags/?$", ProblemTagAPI.as_view(), name="problem_tag_list_api"), url(r"^problem/tags/?$", ProblemTagAPI.as_view(), name="problem_tag_list_api"),
url(r"^problems/?$", ProblemAPI.as_view(), name="problem_list_api"), url(r"^problems/?$", ProblemAPI.as_view(), name="problem_list_api"),
url(r"^contest_problems/?$", ContestProblemAPI.as_view(), name="contest_problem_api"),
] ]

View File

@ -1,8 +1,9 @@
from django.db.models import Q from django.db.models import Q
from utils.api import APIView from utils.api import APIView
from account.decorators import login_required, check_contest_permission
from ..models import ProblemTag, Problem from ..models import ProblemTag, Problem, ContestProblem
from ..serializers import ProblemSerializer, TagSerializer from ..serializers import ProblemSerializer, TagSerializer
from ..serializers import ContestProblemSerializer
class ProblemTagAPI(APIView): class ProblemTagAPI(APIView):
@ -42,3 +43,10 @@ class ProblemAPI(APIView):
problems = problems.filter(difficulty=difficulty_rank) problems = problems.filter(difficulty=difficulty_rank)
return self.success(self.paginate_data(request, problems, ProblemSerializer)) return self.success(self.paginate_data(request, problems, ProblemSerializer))
class ContestProblemAPI(APIView):
@check_contest_permission
def get(self, request):
contest_problems = ContestProblem.objects.filter(contest=self.contest, visible=True)
return self.success(ContestProblemSerializer(contest_problems, many=True).data)

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2017-07-17 13:24
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('submission', '0003_auto_20170704_1243'),
]
operations = [
migrations.AlterModelOptions(
name='submission',
options={'ordering': ('-created_time',)},
),
]

View File

@ -42,6 +42,7 @@ class Submission(models.Model):
class Meta: class Meta:
db_table = "submission" db_table = "submission"
ordering = ("-created_time",)
def __str__(self): def __str__(self):
return self.id return self.id

View File

@ -4,7 +4,7 @@ from rest_framework import serializers
class DateTimeTZField(serializers.DateTimeField): class DateTimeTZField(serializers.DateTimeField):
def to_representation(self, value): def to_representation(self, value):
# self.format = "%Y-%-m-%d %H:%M:%S %Z" # self.format = "%Y-%m-%d %H:%M:%S %Z"
value = timezone.localtime(value) value = timezone.localtime(value)
return super(DateTimeTZField, self).to_representation(value) return super(DateTimeTZField, self).to_representation(value)