mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-11-04 14:49:58 +08:00
contest and contest_problems api.
add ordering for contest and submission models
This commit is contained in:
parent
ee2f5f5dd7
commit
53d0cae8ea
@ -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
|
||||||
|
|||||||
19
contest/migrations/0004_auto_20170717_1324.py
Normal file
19
contest/migrations/0004_auto_20170717_1324.py
Normal 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',)},
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -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):
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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"),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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"]
|
||||||
|
|||||||
@ -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
|
||||||
@ -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"),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
19
submission/migrations/0004_auto_20170717_1324.py
Normal file
19
submission/migrations/0004_auto_20170717_1324.py
Normal 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',)},
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user