Merge branch 'dev'

* dev:
  修改 admin 界面,ip 太宽了
  jquery选择器参数字符串里多打了一个空格
  修复小组邀请赛的密码验证的问题,感觉之前测试过了呀,结果还是有问题,因为验证密码api里选择比赛时限定比赛类型中只有带密码的公开赛,所以无法验证带密码的小组赛

Conflicts:
	judge_dispatcher/tasks.py
	oj/settings.py
	static/src/js/build.js
	static/src/js/config.js
This commit is contained in:
virusdefender 2015-12-23 00:36:21 +08:00
commit 0483fa2496
18 changed files with 475 additions and 138 deletions

View File

@ -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:

View File

@ -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"比赛不存在")

View File

@ -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,
),
]

View File

@ -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否则取到的是旧数据

View File

@ -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

View File

@ -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()

71
judge_dispatcher/views.py Normal file
View File

@ -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)

View File

View File

@ -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})

View File

@ -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"),
@ -57,7 +55,6 @@ urlpatterns = [
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"),
url(r'^api/admin/contest/$', ContestAdminAPIView.as_view(), name="contest_admin_api"),
@ -66,16 +63,17 @@ urlpatterns = [
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<contest_id>\d+)/problem/(?P<contest_problem_id>\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<page>\d+)/$', "contest.views.contest_list_page", name="contest_list_page"),
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
url(r'^problems/$', "problem.views.problem_list_page", name="problem_list_page"),
url(r'^problems/(?P<page>\d+)/$', "problem.views.problem_list_page", name="problem_list_page"),
url(r'^problem/(?P<problem_id>\d+)/submissions/$', "submission.views.problem_my_submissions_list_page",
name="problem_my_submissions_page"),
url(r'^submission/(?P<submission_id>\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<page>\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"),

View File

@ -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,14 +91,14 @@ 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;
}
}
@ -104,7 +106,6 @@ require(["jquery", "avalon", "csrfToken", "bsAlert", "bootstrap"], function ($,
});
avalon.scan();
window.onhashchange = function () {
@ -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("请求失败");
}
});

View File

@ -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();
});

View File

@ -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);
});

View File

@ -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({

View File

@ -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"
},

View File

@ -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",

View File

@ -0,0 +1,131 @@
<div ms-controller="judges" class="col-md-9">
<h1>判题服务器管理</h1>
<table class="table table-striped">
<tr>
<th>编号</th>
<th>名字</th>
<th>最大实例数量</th>
<th>负载</th>
<th>创建时间</th>
<th>状态</th>
<th></th>
</tr>
<tr ms-repeat="judgesList">
<td>{{ el.id }}</td>
<td>{{ el.name }}</td>
<td>{{ el.max_instance_number }}</td>
<td>{{ el.workload }}</td>
<td>{{ el.create_time|date("yyyy-MM-dd HH:mm:ss")}}</td>
<td ms-text="el.status?'启用':'停用'"></td>
<td>
<button class="btn-sm btn-info" ms-click="editJudges(el)">编辑</button>
</td>
</tr>
</table>
<div class="form-group">
<label>仅显示启用 <input ms-duplex-checked="showEnableOnly" type="checkbox"/></label>
</div>
<div class="right">
<ms:pager $id="judgesPager" config="pager"></ms:pager>
</div>
<div ms-visible="isEditing">
<h3>编辑判题服务器</h3>
<form id="edit-judges-form">
<div class="col-md-12">
<div class="col-md-6">
<div class="form-group">
<label>名字</label>
<input name="title" type="text" class="form-control" placeholder="名字" maxlength="30" ms-duplex="name" required data-error="请填写合法的服务器名称">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>口令</label>
<input name="title" type="text" class="form-control" ms-duplex="token" placeholder="口令" maxlength="30" required data-error="请填写合法的口令">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>IP</label>
<input name="ip" type="text" class="form-control" ms-duplex="ipAddress" placeholder="IP" required data-error="请填写合法的IP地址">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>端口</label>
<input name="port" type="number" class="form-control" ms-duplex="port" placeholder="端口" required data-error="请填写合法的端口号">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>最大实例数量</label>
<input type="number" class="form-control" placeholder="最大实例数量" ms-duplex="max_instance_number" required data-error="请填写合法的最大实例数量">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<label>启用 <input ms-duplex-checked="status" type="checkbox"/></label>
</div>
<div class="form-group">
<button class="btn btn-success">保存修改</button>
&nbsp;&nbsp;
<a ms-click="cancelEdit()" class="btn btn-danger">取消</a>
</div>
</div>
</form>
</div>
<h3>添加判题服务器</h3>
<form id="judges-form">
<div class="form-group">
<div class="col-md-12">
<div class="col-md-6">
<div class="form-group">
<label>名字</label>
<input name="title" type="text" class="form-control" id="name" placeholder="名字" maxlength="30" required data-error="请填写合法的服务器名称">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label>口令</label>
<input name="title" type="text" class="form-control" id="token" placeholder="口令" maxlength="30" required data-error="请填写合法的口令">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>IP</label>
<input name="ip" type="text" class="form-control" id="ipAddress" placeholder="IP" required data-error="请填写合法的IP地址">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>端口</label>
<input name="port" type="number" class="form-control" id="port" placeholder="端口" required data-error="请填写合法的端口号">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="col-md-4">
<div class="form-group">
<label>最大实例数量</label>
<input type="number" class="form-control" placeholder="最大实例数量" id="max_instance_number" required data-error="请填写合法的最大实例数量">
<div class="help-block with-errors"></div>
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-success">添加</button>
</div>
</div>
</form>
</div>
<script src="/static/js/app/admin/judges/judges.js"></script>

View File

@ -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)