diff --git a/contest/models.py b/contest/models.py index 591b54af..fc863ff9 100644 --- a/contest/models.py +++ b/contest/models.py @@ -110,7 +110,8 @@ class ContestRank(models.Model): # 之前已经提交过,但是是错误的,这次提交是正确的。错误的题目不计入罚时 self.total_time += (info["ac_time"] + info["error_number"] * 20 * 60) problem = ContestProblem.objects.get(id=submission.problem_id) - if problem.total_accepted_number == 0: + # 更新题目计数器在前 所以是1 + if problem.total_accepted_number == 1: info["is_first_ac"] = True else: @@ -128,7 +129,7 @@ class ContestRank(models.Model): self.total_time += info["ac_time"] problem = ContestProblem.objects.get(id=submission.problem_id) - if problem.total_accepted_number == 0: + if problem.total_accepted_number == 1: info["is_first_ac"] = True else: diff --git a/contest/views.py b/contest/views.py index cfc2049b..d1787028 100644 --- a/contest/views.py +++ b/contest/views.py @@ -308,7 +308,7 @@ class ContestPasswordVerifyAPIView(APIView): if serializer.is_valid(): data = request.data try: - contest = Contest.objects.get(id=data["contest_id"], contest_type=PASSWORD_PROTECTED_CONTEST) + contest = Contest.objects.get(id=data["contest_id"], contest_type__in=[PASSWORD_PROTECTED_CONTEST,PASSWORD_PROTECTED_GROUP_CONTEST]) except Contest.DoesNotExist: return error_response(u"比赛不存在") diff --git a/judge_dispatcher/migrations/0003_auto_20151223_0029.py b/judge_dispatcher/migrations/0003_auto_20151223_0029.py new file mode 100644 index 00000000..fe2e13af --- /dev/null +++ b/judge_dispatcher/migrations/0003_auto_20151223_0029.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('judge_dispatcher', '0002_auto_20151207_2310'), + ] + + operations = [ + migrations.AddField( + model_name='judgeserver', + name='create_time', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='judgeserver', + name='name', + field=models.CharField(default='judger', max_length=30), + preserve_default=False, + ), + ] diff --git a/judge_dispatcher/models.py b/judge_dispatcher/models.py index 7ec5af8f..3bac9474 100644 --- a/judge_dispatcher/models.py +++ b/judge_dispatcher/models.py @@ -3,6 +3,7 @@ from django.db import models class JudgeServer(models.Model): + name = models.CharField(max_length=30) ip = models.GenericIPAddressField() port = models.IntegerField() # 这个服务器最大可能运行的判题实例数量 @@ -14,6 +15,7 @@ class JudgeServer(models.Model): lock = models.BooleanField(default=False) # status 为 false 的时候代表不使用这个服务器 status = models.BooleanField(default=True) + create_time = models.DateTimeField(auto_now_add=True, blank=True, null=True) def use_judge_instance(self): # 因为use 和 release 中间是判题时间,可能这个 model 的数据已经被修改了,所以不能直接使用self.xxx,否则取到的是旧数据 diff --git a/judge_dispatcher/serializers.py b/judge_dispatcher/serializers.py new file mode 100644 index 00000000..4328eee9 --- /dev/null +++ b/judge_dispatcher/serializers.py @@ -0,0 +1,29 @@ +# coding=utf-8 +import json +from rest_framework import serializers +from .models import JudgeServer + + +class CreateJudgesSerializer(serializers.Serializer): + name = serializers.CharField(max_length=30) + ip = serializers.IPAddressField() + port = serializers.IntegerField() + # 这个服务器最大可能运行的判题实例数量 + max_instance_number = serializers.IntegerField() + token = serializers.CharField(max_length=30) + + +class EditJudgesSerializer(serializers.Serializer): + id = serializers.IntegerField() + name = serializers.CharField(max_length=30) + ip = serializers.IPAddressField() + port = serializers.IntegerField() + # 这个服务器最大可能运行的判题实例数量 + max_instance_number = serializers.IntegerField() + token = serializers.CharField(max_length=30) + status = serializers.BooleanField() + + +class JudgesSerializer(serializers.ModelSerializer): + class Meta: + model = JudgeServer diff --git a/judge_dispatcher/tasks.py b/judge_dispatcher/tasks.py index 4f1b366a..76d280f1 100644 --- a/judge_dispatcher/tasks.py +++ b/judge_dispatcher/tasks.py @@ -90,8 +90,8 @@ class JudgeDispatcher(object): waiting_submission.delete() _judge.delay(submission, time_limit=waiting_submission.time_limit, - memory_limit=waiting_submission.memory_limit, test_case_id=waiting_submission.test_case_id, - is_waiting_task=True) + memory_limit=waiting_submission.memory_limit, + test_case_id=waiting_submission.test_case_id, is_waiting_task=True) def update_problem_status(self): problem = Problem.objects.get(id=self.submission.problem_id) @@ -119,7 +119,8 @@ class JudgeDispatcher(object): logger.info("Contest debug mode, id: " + str(contest.id) + ", submission id: " + self.submission.id) return with transaction.atomic(): - contest_problem = ContestProblem.objects.select_for_update().get(contest=contest, id=self.submission.problem_id) + contest_problem = ContestProblem.objects.select_for_update().get(contest=contest, + id=self.submission.problem_id) contest_problem.add_submission_number() diff --git a/judge_dispatcher/views.py b/judge_dispatcher/views.py new file mode 100644 index 00000000..75f09990 --- /dev/null +++ b/judge_dispatcher/views.py @@ -0,0 +1,71 @@ +# coding=utf-8 +from rest_framework.views import APIView + +from account.decorators import super_admin_required +from utils.shortcuts import success_response, serializer_invalid_response, error_response, paginate +from .serializers import CreateJudgesSerializer, JudgesSerializer, EditJudgesSerializer +from .models import JudgeServer + + +class AdminJudgeServerAPIView(APIView): + @super_admin_required + def post(self, request): + """ + 添加判题服务器 json api接口 + --- + request_serializer: CreateJudgesSerializer + response_serializer: JudgesSerializer + """ + serializer = CreateJudgesSerializer(data=request.data) + if serializer.is_valid(): + data = serializer.data + judge_server = JudgeServer.objects.create(name=data["name"], ip=data["ip"], port=data["port"], + max_instance_number=data["max_instance_number"], + token=data["token"], + created_by=request.user) + return success_response(JudgesSerializer(judge_server).data) + else: + return serializer_invalid_response(serializer) + + @super_admin_required + def put(self, request): + """ + 修改判题服务器信息 json api接口 + --- + request_serializer: EditJudgesSerializer + response_serializer: JudgesSerializer + """ + serializer = EditJudgesSerializer(data=request.data) + if serializer.is_valid(): + data = serializer.data + try: + judge_server = JudgeServer.objects.get(pk=data["id"]) + except JudgeServer.DoesNotExist: + return error_response(u"此判题服务器不存在!") + + judge_server.name = data["name"] + judge_server.ip = data["ip"] + judge_server.port = data["port"] + judge_server.max_instance_number = data["max_instance_number"] + judge_server.token = data["token"] + judge_server.status = data["status"] + judge_server.save() + return success_response(JudgesSerializer(judge_server).data) + else: + return serializer_invalid_response(serializer) + + @super_admin_required + def get(self, request): + """ + 获取全部判题服务器 + """ + judge_server_id = request.GET.get("judge_server_id", None) + if judge_server_id: + try: + judge_server = JudgeServer.objects.get(id=judge_server_id) + except JudgeServer.DoesNotExist: + return error_response(u"判题服务器不存在") + return success_response(JudgesSerializer(judge_server).data) + judge_server = JudgeServer.objects.all() + + return paginate(request, judge_server, JudgesSerializer) diff --git a/monitor/__init__.py b/monitor/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/monitor/views.py b/monitor/views.py deleted file mode 100644 index f502579f..00000000 --- a/monitor/views.py +++ /dev/null @@ -1,19 +0,0 @@ -# coding=utf-8 -import redis -import datetime -from rest_framework.views import APIView -from judge.result import result -from django.conf import settings -from utils.shortcuts import success_response -from submission.models import Submission - - -class QueueLengthMonitorAPIView(APIView): - def get(self, request): - r = redis.Redis(host=settings.redis_config["host"], port=settings.redis_config["port"], db=settings.redis_config["db"]) - waiting_number = r.get("judge_queue_length") - if waiting_number is None: - waiting_number = 0 - now = datetime.datetime.now() - return success_response({"time": ":".join([str(now.hour), str(now.minute), str(now.second)]), - "count": waiting_number}) \ No newline at end of file diff --git a/oj/urls.py b/oj/urls.py index fe86966f..fea74415 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -23,11 +23,9 @@ from admin.views import AdminTemplateView from problem.views import TestCaseUploadAPIView, ProblemTagAdminAPIView, ProblemAdminAPIView from submission.views import (SubmissionAPIView, SubmissionAdminAPIView, ContestSubmissionAPIView, SubmissionShareAPIView, SubmissionRejudgeAdminAPIView) -from monitor.views import QueueLengthMonitorAPIView +from judge_dispatcher.views import AdminJudgeServerAPIView from utils.views import SimditorImageUploadAPIView - - urlpatterns = [ url("^$", "account.views.index_page", name="index_page"), @@ -56,7 +54,6 @@ urlpatterns = [ url(r'^api/contest/submission/$', ContestSubmissionAPIView.as_view(), name="contest_submission_api"), url(r'^api/submission/$', SubmissionAPIView.as_view(), name="submission_api"), url(r'^api/group_join/$', JoinGroupAPIView.as_view(), name="group_join_api"), - url(r'^api/admin/upload_image/$', SimditorImageUploadAPIView.as_view(), name="simditor_upload_image"), url(r'^api/admin/announcement/$', AnnouncementAdminAPIView.as_view(), name="announcement_admin_api"), @@ -65,17 +62,18 @@ urlpatterns = [ url(r'^api/admin/group/$', GroupAdminAPIView.as_view(), name="group_admin_api"), url(r'^api/admin/group_member/$', GroupMemberAdminAPIView.as_view(), name="group_member_admin_api"), url(r'^api/admin/group/promot_as_admin/$', GroupPrometAdminAPIView.as_view(), name="group_promote_admin_api"), - url(r'^api/admin/problem/$', ProblemAdminAPIView.as_view(), name="problem_admin_api"), url(r'^api/admin/contest_problem/$', ContestProblemAdminAPIView.as_view(), name="contest_problem_admin_api"), - url(r'^api/admin/contest_problem/public/', MakeContestProblemPublicAPIView.as_view(), name="make_contest_problem_public"), + url(r'^api/admin/contest_problem/public/', MakeContestProblemPublicAPIView.as_view(), + name="make_contest_problem_public"), url(r'^api/admin/test_case_upload/$', TestCaseUploadAPIView.as_view(), name="test_case_upload_api"), url(r'^api/admin/tag/$', ProblemTagAdminAPIView.as_view(), name="problem_tag_admin_api"), url(r'^api/admin/join_group_request/$', JoinGroupRequestAdminAPIView.as_view(), name="join_group_request_admin_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'^api/admin/judges/$', AdminJudgeServerAPIView.as_view(), name="judges_admin_api"), url(r'^contest/(?P\d+)/problem/(?P\d+)/$', "contest.views.contest_problem_page", name="contest_problem_page"), @@ -94,14 +92,12 @@ urlpatterns = [ url(r'^contests/$', "contest.views.contest_list_page", name="contest_list_page"), url(r'^contests/(?P\d+)/$', "contest.views.contest_list_page", name="contest_list_page"), - url(r'^problem/(?P\d+)/$', "problem.views.problem_page", name="problem_page"), url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"), url(r'^problems/(?P\d+)/$', "problem.views.problem_list_page", name="problem_list_page"), url(r'^problem/(?P\d+)/submissions/$', "submission.views.problem_my_submissions_list_page", name="problem_my_submissions_page"), - url(r'^submission/(?P\w+)/$', "submission.views.my_submission", name="my_submission_page"), url(r'^submissions/$', "submission.views.my_submission_list_page", name="my_submission_list_page"), url(r'^submissions/(?P\d+)/$', "submission.views.my_submission_list_page", name="my_submission_list_page"), @@ -128,8 +124,10 @@ urlpatterns = [ url(r'^api/apply_reset_password/$', ApplyResetPasswordAPIView.as_view(), name="apply_reset_password_api"), url(r'^api/reset_password/$', ResetPasswordAPIView.as_view(), name="apply_reset_password_api"), - url(r'^account/settings/$', TemplateView.as_view(template_name="oj/account/settings.html"), name="account_setting_page"), - url(r'^account/settings/avatar/$', TemplateView.as_view(template_name="oj/account/avatar.html"), name="avatar_settings_page"), + url(r'^account/settings/$', TemplateView.as_view(template_name="oj/account/settings.html"), + name="account_setting_page"), + url(r'^account/settings/avatar/$', TemplateView.as_view(template_name="oj/account/avatar.html"), + name="avatar_settings_page"), url(r'^account/sso/$', SSOAPIView.as_view(), name="sso_api"), url(r'^api/account/userprofile/$', UserProfileAPIView.as_view(), name="userprofile_api"), url(r'^reset_password/$', TemplateView.as_view(template_name="oj/account/apply_reset_password.html"), name="apply_reset_password_page"), @@ -140,4 +138,4 @@ urlpatterns = [ if settings.DEBUG: - urlpatterns.append(url(r'^docs/', include('rest_framework_swagger.urls'))) \ No newline at end of file + urlpatterns.append(url(r'^docs/', include('rest_framework_swagger.urls'))) diff --git a/static/src/js/app/admin/admin.js b/static/src/js/app/admin/admin.js index 2c527de7..ec75de13 100644 --- a/static/src/js/app/admin/admin.js +++ b/static/src/js/app/admin/admin.js @@ -22,46 +22,48 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "bootstrap"], function ($, } var superAdminNav = [ - { name: "首页", - children: [{name: "主页", hash: "#index/index"}, - {name: "监控", hash: "#monitor/monitor"}] - }, - { - name: "通用", - children: [{name: "公告管理", hash: "#announcement/announcement"}, - {name: "用户管理", hash: "#user/user_list"}] - }, - { - name: "题目管理", - children: [{name: "题目列表", hash: "#problem/problem_list"}, - {name: "创建题目", hash: "#problem/add_problem"}] - }, - { - name: "比赛管理", - children: [{name: "比赛列表", hash: "#contest/contest_list"}, - {name: "创建比赛", hash: "#contest/add_contest"}] - }, - { - name: "小组管理", - children: [{name: "小组列表", hash: "#group/group"}, - {name: "加入小组请求", hash: "#group/join_group_request_list"}] - } + { + name: "首页", + children: [{name: "主页", hash: "#index/index"}, + {name: "判题服务器", hash: "#judges/judges"}] + }, + { + name: "通用", + children: [{name: "公告管理", hash: "#announcement/announcement"}, + {name: "用户管理", hash: "#user/user_list"}] + }, + { + name: "题目管理", + children: [{name: "题目列表", hash: "#problem/problem_list"}, + {name: "创建题目", hash: "#problem/add_problem"}] + }, + { + name: "比赛管理", + children: [{name: "比赛列表", hash: "#contest/contest_list"}, + {name: "创建比赛", hash: "#contest/add_contest"}] + }, + { + name: "小组管理", + children: [{name: "小组列表", hash: "#group/group"}, + {name: "加入小组请求", hash: "#group/join_group_request_list"}] + } ]; var adminNav = [ - { name: "首页", - children: [{name: "主页", hash: "#index/index"}] - }, - { - name: "比赛管理", - children: [{name: "比赛列表", hash: "#contest/contest_list"}, - {name: "创建比赛", hash: "#contest/add_contest"}] - }, - { - name: "小组管理", - children: [{name: "小组列表", hash: "#group/group"}, - {name: "加入小组请求", hash: "#group/join_group_request_list"}] - } + { + name: "首页", + children: [{name: "主页", hash: "#index/index"}] + }, + { + name: "比赛管理", + children: [{name: "比赛列表", hash: "#contest/contest_list"}, + {name: "创建比赛", hash: "#contest/add_contest"}] + }, + { + name: "小组管理", + children: [{name: "小组列表", hash: "#group/group"}, + {name: "加入小组请求", hash: "#group/join_group_request_list"}] + } ]; var vm = avalon.define({ @@ -79,7 +81,7 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "bootstrap"], function ($, hide_loading: function () { $("#loading-gif").hide(); }, - getLiId: function(hash){ + getLiId: function (hash) { return hash.replace("#", "li-").replace("/", "-"); } }); @@ -89,21 +91,20 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "bootstrap"], function ($, url: "/api/user/", method: "get", dataType: "json", - success: function(data){ - if(!data.code){ + success: function (data) { + if (!data.code) { vm.username = data.data.username; vm.adminType = data.data.admin_type; - if (data.data.admin_type == 2){ + if (data.data.admin_type == 2) { vm.adminNavList = superAdminNav; } - else{ + else { vm.adminNavList = adminNav; } } } }); - avalon.scan(); @@ -115,12 +116,14 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "bootstrap"], function ($, show_template("template/" + hash + ".html"); } }; - setTimeout(function(){li_active("#li-" + hash.replace("/", "-"));}, 500); + setTimeout(function () { + li_active("#li-" + hash.replace("/", "-")); + }, 500); $.ajaxSetup({ - beforeSend: csrfTokenHeader, + beforeSend: csrfTokenHeader, dataType: "json", - error: function(){ + error: function () { bsAlert("请求失败"); } }); diff --git a/static/src/js/app/admin/judges/judges.js b/static/src/js/app/admin/judges/judges.js new file mode 100644 index 00000000..6e651f23 --- /dev/null +++ b/static/src/js/app/admin/judges/judges.js @@ -0,0 +1,143 @@ +require(["jquery", "avalon", "csrfToken", "bsAlert", "validator", "pager"], + function ($, avalon, csrfTokenHeader, bsAlert, editor) { + avalon.ready(function () { + + if (avalon.vmodels.judges) { + var vm = avalon.vmodels.judges; + } + else { + var vm = avalon.define({ + $id: "judges", + judgesList: [], + isEditing: false, + showEnableOnly: false, + + //编辑器同步变量 + max_instance_number: 0, + ipAddress: "", + port: 0, + status: true, + judgesId: -1, + name: "", + token: "", + id: 0, + pager: { + getPage: function (page) { + getPage(page); + } + }, + editJudges: function (judges) { + vm.id = judges.id; + vm.name = judges.name; + vm.judgesId = judges.id; + vm.status = judges.status; + vm.port = judges.port; + vm.ipAddress = judges.ip; + vm.max_instance_number = judges.max_instance_number; + vm.token = judges.token; + vm.isEditing = true; + }, + cancelEdit: function () { + vm.isEditing = false; + } + }); + vm.$watch("showEnableOnly", function () { + getPage(1); + avalon.vmodels.judgesPager.currentPage = 1; + }); + } + + function getPage(page) { + var url = "/api/admin/judges/?paging=true&page=" + page + "&page_size=20"; + if (vm.showEnableNnly) + url += "&status=true"; + $.ajax({ + url: url, + method: "get", + success: function (data) { + if (!data.code) { + vm.judgesList = data.data.results; + avalon.vmodels.judgesPager.totalPage = data.data.total_page; + } + else { + bsAlert(data.data); + } + } + }); + } + + $("#judges-form").validator().on('submit', function (e) { + if (!e.isDefaultPrevented()) { + var name = $("#name").val(); + var max_instance_number = $("#max_instance_number").val(); + var ip = $("#ipAddress").val(); + var port = $("#port").val(); + var token = $("#token").val(); + $.ajax({ + url: "/api/admin/judges/", + contentType: "application/json", + data: JSON.stringify({ + name: name, + ip: ip, + port: port, + token: token, + max_instance_number: max_instance_number + }), + dataType: "json", + method: "post", + success: function (data) { + if (!data.code) { + bsAlert("提交成功!"); + $("#name").val(""); + $("#max_instance_number").val(""); + $("#ipAddress").val(""); + $("#port").val(""); + $("#token").val(""); + getPage(1); + } else { + bsAlert(data.data); + } + } + }); + return false; + } + }); + + $("#edit-judges-form").validator().on('submit', function (e) { + if (!e.isDefaultPrevented()) { + var name = vm.name; + var max_instance_number = vm.max_instance_number; + var ip = vm.ipAddress; + var port = vm.port; + var token = vm.token; + var status = vm.status; + var id = vm.id; + $.ajax({ + url: "/api/admin/judges/", + contentType: "application/json", + data: JSON.stringify({ + id: id, + name: name, + ip: ip, + port: port, + token: token, + max_instance_number: max_instance_number, + status: status + }), + dataType: "json", + method: "put", + success: function (data) { + if (!data.code) { + bsAlert("提交成功!"); + getPage(1); + } else { + bsAlert(data.data); + } + } + }); + return false; + } + }); + }); + avalon.scan(); + }); \ No newline at end of file diff --git a/static/src/js/app/admin/monitor/monitor.js b/static/src/js/app/admin/monitor/monitor.js deleted file mode 100644 index 1a0e46f1..00000000 --- a/static/src/js/app/admin/monitor/monitor.js +++ /dev/null @@ -1,48 +0,0 @@ -require(["jquery", "chart"], function ($, Chart) { - var data = { - labels: ["初始化"], - datasets: [ - { - label: "队列长度", - fillColor: "rgba(255,255,255,0.2)", - strokeColor: "rgba(151,187,205,1)", - pointColor: "rgba(151,187,205,1)", - pointStrokeColor: "#fff", - pointHighlightFill: "#fff", - pointHighlightStroke: "rgba(151,187,205,1)", - data: [0] - } - ] - }; - var chart = new Chart($("#waiting-queue-chart").get(0).getContext("2d")).Line(data); - - var dataCounter = 0; - - function getMonitorData(){ - var hash = location.hash; - if (hash != "#monitor/monitor"){ - clearInterval(intervalId); - } - $.ajax({ - url: "/api/admin/monitor/", - method: "get", - dataType: "json", - success: function(data){ - if(!data.code){ - chart.addData([data.data["count"]], data.data["time"]) - dataCounter ++; - } - } - }) - } - - $("#clear-chart-data").click(function(){ - for(var i = 0;i < dataCounter;i++) { - chart.removeData(); - } - dataCounter = 0; - }); - - var intervalId = setInterval(getMonitorData, 3000); - -}); \ No newline at end of file diff --git a/static/src/js/app/oj/account/changePassword.js b/static/src/js/app/oj/account/changePassword.js index fe7d908a..e825285a 100644 --- a/static/src/js/app/oj/account/changePassword.js +++ b/static/src/js/app/oj/account/changePassword.js @@ -10,7 +10,7 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c $('form').validator().on('submit', function (e) { e.preventDefault(); - var newPassword = $("#new_password ").val(); + var newPassword = $("#new_password").val(); var password = $("#password").val(); var captcha = $("#captcha").val(); $.ajax({ diff --git a/static/src/js/build.js b/static/src/js/build.js index 3688d1f7..df5e2343 100644 --- a/static/src/js/build.js +++ b/static/src/js/build.js @@ -68,7 +68,6 @@ addContest_13_pack: "app/admin/contest/addContest", contestPassword_14_pack: "app/oj/contest/contestPassword", changePassword_15_pack: "app/oj/account/changePassword", - monitor_16_pack: "app/admin/monitor/monitor", editProblem_17_pack: "app/admin/contest/editProblem", joinGroupRequestList_18_pack: "app/admin/group/joinGroupRequestList", group_19_pack: "app/oj/group/group", @@ -138,9 +137,6 @@ { name: "changePassword_15_pack" }, - { - name: "monitor_16_pack" - }, { name: "editProblem_17_pack" }, diff --git a/static/src/js/config.js b/static/src/js/config.js index d860d68b..531d349e 100644 --- a/static/src/js/config.js +++ b/static/src/js/config.js @@ -70,7 +70,6 @@ var require = { addContest_13_pack: "app/admin/contest/addContest", contestPassword_14_pack: "app/oj/contest/contestPassword", changePassword_15_pack: "app/oj/account/changePassword", - monitor_16_pack: "app/admin/monitor/monitor", editProblem_17_pack: "app/admin/contest/editProblem", joinGroupRequestList_18_pack: "app/admin/group/joinGroupRequestList", group_19_pack: "app/oj/group/group", diff --git a/template/src/admin/judges/judges.html b/template/src/admin/judges/judges.html new file mode 100644 index 00000000..11ef8e91 --- /dev/null +++ b/template/src/admin/judges/judges.html @@ -0,0 +1,131 @@ +
+

判题服务器管理

+ + + + + + + + + + + + + + + + + + + +
编号名字最大实例数量负载创建时间状态
{{ el.id }}{{ el.name }}{{ el.max_instance_number }}{{ el.workload }}{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}} + +
+
+ +
+
+ +
+ +
+

编辑判题服务器

+ +
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+ +
+ +
+ +    + 取消 +
+
+
+
+ +

添加判题服务器

+ +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+ +
+
+ +
+ \ No newline at end of file diff --git a/utils/shortcuts.py b/utils/shortcuts.py index e3af9160..2f0e1c65 100644 --- a/utils/shortcuts.py +++ b/utils/shortcuts.py @@ -2,6 +2,7 @@ import hashlib import time import random +import logging from django.shortcuts import render from django.core.paginator import Paginator @@ -9,6 +10,9 @@ from django.core.paginator import Paginator from rest_framework.response import Response +logger = logging.getLogger("app_info") + + def error_page(request, error_reason): return render(request, "utils/error.html", {"error": error_reason}) @@ -96,7 +100,8 @@ def paginate_data(request, query_set, object_serializer): def paginate(request, query_set, object_serializer=None): try: data= paginate_data(request, query_set, object_serializer) - except Exception: + except Exception as e: + logger.error(str(e)) return error_response(u"参数错误") return success_response(data)