From 1fe35bd6e0ed529156141e3eaf8ca3c3dd25c8c0 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Sat, 22 Aug 2015 20:46:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E4=BA=86=E5=8D=95=E4=B8=AA?= =?UTF-8?q?=E6=AF=94=E8=B5=9B=E7=9A=84=E8=AF=A6=E6=83=85=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contest/models.py | 4 +- contest/serializers.py | 5 ++ contest/views.py | 66 +++++++++++++++++-- oj/urls.py | 4 +- .../src/js/app/oj/contest/contest_password.js | 24 +++++++ template/oj/contest/_contest_header.html | 38 +++++++++++ template/oj/contest/contest_index.html | 21 ++++++ template/oj/contest/contest_no_privilege.html | 26 ++++++++ 8 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 static/src/js/app/oj/contest/contest_password.js create mode 100644 template/oj/contest/_contest_header.html create mode 100644 template/oj/contest/contest_index.html create mode 100644 template/oj/contest/contest_no_privilege.html diff --git a/contest/models.py b/contest/models.py index 0ece5ff..3611c3a 100644 --- a/contest/models.py +++ b/contest/models.py @@ -9,19 +9,17 @@ from group.models import Group class Contest(models.Model): title = models.CharField(max_length=40, unique=True) description = models.TextField() - # 比赛模式:0 即为是acm模式,1 即为是按照总的 ac 题目数量排名模式,2 即为按照 ac 的题目的总分排名模式 + # 比赛模式:0 即为是acm模式,1 即为是按照总的 ac 题目数量排名模式 mode = models.IntegerField() # 是否显示排名结果 show_rank = models.BooleanField() # 是否显示别人的提交记录 show_user_submission = models.BooleanField() - # 只能超级管理员创建公开赛,管理员只能创建小组内部的比赛 # 如果这一项不为空,即为有密码的公开赛,没有密码的可以为小组赛或者是公开赛(此时用比赛的类型来表示) password = models.CharField(max_length=30, blank=True, null=True) # 比赛的类型: 0 即为是小组赛,1 即为是无密码的公开赛,2 即为是有密码的公开赛 contest_type = models.IntegerField() - # 开始时间 start_time = models.DateTimeField() # 结束时间 diff --git a/contest/serializers.py b/contest/serializers.py index dd9f370..23d8474 100644 --- a/contest/serializers.py +++ b/contest/serializers.py @@ -103,3 +103,8 @@ class EditContestProblemSerializer(serializers.Serializer): sort_index = serializers.CharField(max_length=30) +class ContestPasswordVerifySerializer(serializers.Serializer): + contest_id = serializers.IntegerField() + password = serializers.CharField(max_length=30) + + diff --git a/contest/views.py b/contest/views.py index d00bee5..34271b1 100644 --- a/contest/views.py +++ b/contest/views.py @@ -9,15 +9,13 @@ from utils.shortcuts import (serializer_invalid_response, error_response, success_response, paginate, rand_str, error_page) from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN +from account.decorators import login_required from group.models import Group from .models import Contest, ContestProblem from .serializers import (CreateContestSerializer, ContestSerializer, EditContestSerializer, - CreateContestProblemSerializer, ContestProblemSerializer, EditContestProblemSerializer) - - -def contest_page(request, contest_id): - pass + CreateContestProblemSerializer, ContestProblemSerializer, + EditContestProblemSerializer, ContestPasswordVerifySerializer) class ContestAdminAPIView(APIView): @@ -220,4 +218,60 @@ class ContestProblemAdminAPIView(APIView): contest_problem = contest_problem.filter(Q(title__contains=keyword) | Q(description__contains=keyword)) - return paginate(request, contest_problem, ContestProblemSerializer) \ No newline at end of file + return paginate(request, contest_problem, ContestProblemSerializer) + + +class ContestPasswordVerifyAPIView(APIView): + @login_required + def post(self, request): + serializer = ContestPasswordVerifySerializer(data=request.data) + if serializer.is_valid(): + data = request.data + try: + contest = Contest.objects.get(id=data["contest_id"], contest_type=2) + except Contest.DoesNotExist: + return error_response(u"密码错误") + + if data["password"] != contest.password: + return error_response(u" 密码错误") + else: + print request.session.get("contests", None) + if "contests" not in request.session: + request.session["contests"] = [] + request.session["contests"].append(int(data["contest_id"])) + print request.session["contests"] + + return success_response(True) + else: + return serializer_invalid_response(serializer) + + +def check_user_contest_permission(request, contest): + # 有密码的公开赛 + if contest.contest_type == 2: + # 没有输入过密码 + if contest.id not in request.session.get("contests", []): + return {"result": False, "reason": "password_protect"} + + # 指定小组参加的 + if contest.contest_type == 0: + if not contest.groups.filter(id__in=request.user.group_set.all()).exists(): + return {"result": False, "reason": "limited_group"} + return {"result": True} + + +@login_required +def contest_page(request, contest_id): + print request.session.get("contests", None) + try: + contest = Contest.objects.get(id=contest_id) + except Contest.DoesNotExist: + return error_page(request, u"比赛不存在") + + Contest.objects.filter(Q(contest_type__in=[1, 2]) | Q(groups__in=request.user.group_set.all())) + + result = check_user_contest_permission(request, contest) + if not result["result"]: + return render(request, "oj/contest/contest_no_privilege.html", {"contenst": contest, "reason": result["reason"]}) + + return render(request, "oj/contest/contest_index.html", {"contest": contest}) \ No newline at end of file diff --git a/oj/urls.py b/oj/urls.py index 6dc7606..2f66950 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -8,7 +8,7 @@ from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterA UserAdminAPIView, UserInfoAPIView) from announcement.views import AnnouncementAdminAPIView -from contest.views import ContestAdminAPIView, ContestProblemAdminAPIView +from contest.views import ContestAdminAPIView, ContestProblemAdminAPIView, ContestPasswordVerifyAPIView from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView, JoinGroupAPIView, JoinGroupRequestAdminAPIView) @@ -64,5 +64,7 @@ urlpatterns = [ url(r'^api/submission/$', SubmissionAPIView.as_view(), name="submission_api"), url(r'^api/admin/submission/$', SubmissionAdminAPIView.as_view(), name="submission_admin_api_view"), url(r'^api/admin/monitor/$', QueueLengthMonitorAPIView.as_view(), name="queue_length_monitor_api"), + url(r'^contest/(?P\d+)/$', "contest.views.contest_page", name="contest_page"), + url(r'^api/contest/password/$', ContestPasswordVerifyAPIView.as_view(), name="contest_password_verify_api"), ] diff --git a/static/src/js/app/oj/contest/contest_password.js b/static/src/js/app/oj/contest/contest_password.js new file mode 100644 index 0000000..24d785f --- /dev/null +++ b/static/src/js/app/oj/contest/contest_password.js @@ -0,0 +1,24 @@ +require(["jquery", "bsAlert", "csrfToken"], function($, bsAlert, csrfTokenHeader){ + $("#contest-password-btn").click(function(){ + var password = $("#contest-password").val(); + if(!password){ + bsAlert("密码不能为空!"); + return; + } + $.ajax({ + beforeSend: csrfTokenHeader, + url: "/api/contest/password/", + data: {password: password, contest_id: location.href.split("/")[4]}, + method: "post", + dataType: "json", + success: function(data){ + if(!data.code){ + location.reload(); + } + else{ + bsAlert(data.data); + } + } + }) + }) +}); \ No newline at end of file diff --git a/template/oj/contest/_contest_header.html b/template/oj/contest/_contest_header.html new file mode 100644 index 0000000..62892ce --- /dev/null +++ b/template/oj/contest/_contest_header.html @@ -0,0 +1,38 @@ +{% load contest %} +

{{ contest.title }}

+ +
+
+ + + + + + + + + + + + + + + + {% ifequal contest.contest_type 0 %} + + {% endifequal %} + {% ifequal contest.contest_type 1 %} + + {% endifequal %} + {% ifequal contest.contest_type 2 %} + + {% endifequal %} + + + + +
开始时间结束时间状态比赛类型创建者
{{ contest.start_time }}{{ contest.end_time }}{{ contest|contest_status }}小组赛公开赛公开赛(密码保护){{ contest.created_by.username }}
+
+
{{ contest.description|safe }}
+
+

\ No newline at end of file diff --git a/template/oj/contest/contest_index.html b/template/oj/contest/contest_index.html new file mode 100644 index 0000000..7d32910 --- /dev/null +++ b/template/oj/contest/contest_index.html @@ -0,0 +1,21 @@ +{% extends 'oj_base.html' %} + +{% block body %} +
+ + {% include "oj/contest/_contest_header.html" %} +
+{% endblock %} \ No newline at end of file diff --git a/template/oj/contest/contest_no_privilege.html b/template/oj/contest/contest_no_privilege.html new file mode 100644 index 0000000..12c7fca --- /dev/null +++ b/template/oj/contest/contest_no_privilege.html @@ -0,0 +1,26 @@ +{% extends 'oj_base.html' %} + +{% block body %} +
+ + {% include "oj/contest/_contest_header.html" %} + {% ifequal reason "password_protect" %} +
+
+ + +
+ +
+ {% else %} + + {% endifequal %} +
+{% endblock %} +{% block js_block %} + +{% endblock %} \ No newline at end of file