Merge branch 'hohoTT-dev' into dev

* hohoTT-dev:
  后端比赛与比赛题目部分已修改完成
  修改并完善比赛及其他部分的内容及测试
  CodeMirror自动更改高度的问题
  增加及修改account与announcement的测试
  修改比赛的views及部分问题
  后端修改比赛创建部分,同时在models中增加了几个字段
  后端比赛和比赛题目的部分,还有要增加和修改的地方
  修复一个点击错误

Conflicts:
	static/src/css/oj.css
This commit is contained in:
virusdefender 2015-08-22 14:12:14 +08:00
commit ea3e8841a9
20 changed files with 1009 additions and 78 deletions

View File

@ -130,7 +130,7 @@ class UserChangePasswordAPITest(APITestCase):
self.assertEqual(response.data, {"code": 1, "data": u"密码不正确,请重新修改!"}) self.assertEqual(response.data, {"code": 1, "data": u"密码不正确,请重新修改!"})
def test_invalid_data_format(self): def test_invalid_data_format(self):
data = {"username": "test", "old_password": "aaa", "new_password": "aaaddd"} data = {"old_password": "aaa", "new_password": "aaaddd"}
response = self.client.post(self.url, data=data) response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 1) self.assertEqual(response.data["code"], 1)
@ -152,15 +152,50 @@ class UserAdminAPITest(APITestCase):
user = User.objects.create(username="testx", real_name="xx", admin_type=SUPER_ADMIN) user = User.objects.create(username="testx", real_name="xx", admin_type=SUPER_ADMIN)
user.set_password("testxx") user.set_password("testxx")
user.save() user.save()
user = User.objects.create(username="testy", real_name="yy", admin_type=SUPER_ADMIN)
user.set_password("testyy")
user.save()
self.client.login(username="testx", password="testxx") self.client.login(username="testx", password="testxx")
# 以下是编辑用户的测试
def test_success_get_data(self): def test_success_get_data(self):
self.assertEqual(self.client.get(self.url).data["code"], 0) self.assertEqual(self.client.get(self.url).data["code"], 0)
def test_put_invalid_data(self):
data = {"username": "test", "password": "testaa", "email": "60@qq.com", "admin_type": "2"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_user_does_not_exist(self):
data = {"id": 3, "username": "test0", "real_name": "test00",
"password": "testaa", "email": "60@qq.com", "admin_type": "2"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"该用户不存在!"})
def test_username_exists(self):
data = {"id": 1, "username": "testy", "real_name": "test00",
"password": "testaa", "email": "60@qq.com", "admin_type": "2"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"昵称已经存在"})
def test_user_edit_not_password_successfully(self):
data = {"id": 1, "username": "test0", "real_name": "test00",
"email": "60@qq.com", "admin_type": "2"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
def test_user_edit_change_password_successfully(self):
data = {"id": 1, "username": "test0", "real_name": "test00", "password": "111111",
"email": "60@qq.com", "admin_type": "2"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
self.assertIsNotNone(auth.authenticate(username="test0", password="111111"))
def test_error_admin_type(self): def test_error_admin_type(self):
response = self.client.get(self.url + "?admin_type=error") response = self.client.get(self.url + "?admin_type=error")
self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) self.assertEqual(response.data, {"code": 1, "data": u"参数错误"})
# 以下是用户分页的测试
def test_query_by_keyword(self): def test_query_by_keyword(self):
user1 = User.objects.create(username="test1", real_name="aa") user1 = User.objects.create(username="test1", real_name="aa")
user1.set_password("testaa") user1.set_password("testaa")
@ -177,29 +212,18 @@ class UserAdminAPITest(APITestCase):
response = self.client.get(self.url + "?keyword=test1") response = self.client.get(self.url + "?keyword=test1")
self.assertEqual(response.data["code"], 0) self.assertEqual(response.data["code"], 0)
def test_put_invalid_data(self):
data = {"username": "test", "password": "testaa", "email": "60@qq.com", "admin_type": "2"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_user_does_not_exist(self): class UserInfoAPITest(APITestCase):
data = {"id": 2, "username": "test0", "real_name": "test00", def setUp(self):
"password": "testaa","email": "60@qq.com", "admin_type": "2"} self.client = APIClient()
response = self.client.put(self.url, data=data) self.url = reverse('user_info_api')
self.assertEqual(response.data, {"code": 1, "data": u"该用户不存在!"}) user = User.objects.create(username="test1", real_name="aa")
user.set_password("testaa")
user.save()
def test_success_user_edit_not_password(self): def test_get_data_successfully(self):
data = {"id": 1, "username": "test0", "real_name": "test00", self.client.login(username="test1", password="testaa")
"email": "60@qq.com", "admin_type": "2"} self.assertEqual(self.client.get(self.url).data["code"], 0)
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
def test_success_user_edit_change_password(self):
data = {"id": 1, "username": "test0", "real_name": "test00", "password": "111111",
"email": "60@qq.com", "admin_type": "2"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
self.assertIsNotNone(auth.authenticate(username="test0", password="111111"))
@login_required @login_required

View File

@ -9,7 +9,7 @@ class CreateAnnouncementSerializer(serializers.Serializer):
title = serializers.CharField(max_length=50) title = serializers.CharField(max_length=50)
content = serializers.CharField(max_length=10000) content = serializers.CharField(max_length=10000)
is_global = serializers.BooleanField() is_global = serializers.BooleanField()
groups = serializers.ListField(child=serializers.IntegerField(), allow_empty=True) groups = serializers.ListField(child=serializers.IntegerField(), required=False, default=[])
class AnnouncementSerializer(serializers.ModelSerializer): class AnnouncementSerializer(serializers.ModelSerializer):
@ -31,4 +31,4 @@ class EditAnnouncementSerializer(serializers.Serializer):
content = serializers.CharField(max_length=10000) content = serializers.CharField(max_length=10000)
visible = serializers.BooleanField() visible = serializers.BooleanField()
is_global = serializers.BooleanField() is_global = serializers.BooleanField()
groups = serializers.ListField(child=serializers.IntegerField()) groups = serializers.ListField(child=serializers.IntegerField(), required=False, default=[])

View File

@ -5,6 +5,7 @@ from django.test import TestCase
from rest_framework.test import APITestCase, APIClient from rest_framework.test import APITestCase, APIClient
from account.models import User from account.models import User
from group.models import Group
from announcement.models import Announcement from announcement.models import Announcement
from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN
@ -13,76 +14,129 @@ class AnnouncementAdminAPITest(APITestCase):
def setUp(self): def setUp(self):
self.client = APIClient() self.client = APIClient()
self.url = reverse("announcement_admin_api") self.url = reverse("announcement_admin_api")
user = User.objects.create(username="test", admin_type=SUPER_ADMIN) user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN)
user.set_password("testaa") user1.set_password("testaa")
user.save() user1.save()
user2 = User.objects.create(username="test2", admin_type=ADMIN)
user2.set_password("testbb")
user2.save()
self.group = Group.objects.create(name="group1", description="des0",
join_group_setting=0, visible=True,
admin=user2)
self.announcement = Announcement.objects.create(title="bb",
content="BB",
created_by=User.objects.get(username="test2"),
is_global=False)
# 以下是发布公告的测试 # 以下是发布公告的测试
def test_invalid_format(self): def test_invalid_format(self):
self.client.login(username="test", password="testaa") self.client.login(username="test1", password="testaa")
data = {"title": "test1"} data = {"title": "test1"}
response = self.client.post(self.url, data=data) response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 1) self.assertEqual(response.data["code"], 1)
def test_success_announcement(self): def test_group_at_least_one(self):
self.client.login(username="test", password="testaa") self.client.login(username="test1", password="testaa")
data = {"title": "title0", "content": "content0"} data = {"title": "title0", "content": "content0", "is_global": False}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"至少选择一个小组"})
def test_global_announcement_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title0", "content": "content0", "is_global": True}
response = self.client.post(self.url, data=data) response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 0, "data": u"公告发布成功!"}) self.assertEqual(response.data, {"code": 0, "data": u"公告发布成功!"})
def test_post_invalid_data(self): def test_group_announcement_successfully(self):
self.client.login(username="test", password="testaa") self.client.login(username="test2", password="testbb")
data = {"title": "test"} data = {"title": "title0", "content": "content0", "is_global": False, "groups": [self.group.id]}
response = self.client.post(self.url, data=data) response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 1) self.assertEqual(response.data, {"code": 0, "data": u"公告发布成功!"})
def test_global_announcement_does_not_has_privileges(self):
self.client.login(username="test2", password="testbb")
data = {"title": "title0", "content": "content0", "is_global": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"只有超级管理员可以创建全局公告"})
# 以下是编辑公告的测试 # 以下是编辑公告的测试
def test_put_invalid_data(self): def test_put_invalid_data(self):
self.client.login(username="test", password="testaa") self.client.login(username="test1", password="testaa")
data = {"title": "test0", "content": "test0", "visible": "True"} data = {"title": "test0", "content": "test0", "visible": "True"}
response = self.client.put(self.url, data=data) response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 1) self.assertEqual(response.data["code"], 1)
def test_announcement_does_not_exist(self): def test_announcement_does_not_exist(self):
self.client.login(username="test", password="testaa") self.client.login(username="test1", password="testaa")
announcement = Announcement.objects.create(title="aa", announcement = Announcement.objects.create(title="aa",
content="AA", content="AA",
created_by=User.objects.get(username="test")) created_by=User.objects.get(username="test1"),
data = {"id": announcement.id + 1, "title": "11", "content": "22", "visible": True} is_global=True)
data = {"id": announcement.id + 1, "title": "11", "content": "22",
"visible": True, "is_global": True}
response = self.client.put(self.url, data=data) response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"该公告不存在!"}) self.assertEqual(response.data, {"code": 1, "data": u"公告不存在"})
def test_success_edit_announcement(self): def test_edit_global_announcement_successfully(self):
self.client.login(username="test", password="testaa") self.client.login(username="test1", password="testaa")
announcement = Announcement.objects.create(title="bb", data = {"id": self.announcement.id, "title": "11", "content": "22",
content="BB", "visible": True, "is_global": True}
created_by=User.objects.get(username="test"))
data = {"id": announcement.id, "title": "11", "content": "22", "visible": True}
response = self.client.put(self.url, data=data) response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0) self.assertEqual(response.data["code"], 0)
def test_edit_group_announcement_successfully(self):
self.client.login(username="test2", password="testbb")
data = {"id": self.announcement.id, "title": "11", "content": "22",
"visible": True, "is_global": False, "groups": [self.group.id]}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
self.assertEqual(response.data["data"]["title"], "11")
self.assertEqual(response.data["data"]["content"], "22")
class AnnouncementAPITest(APITestCase): def test_edit_group_at_least_one(self):
def setUp(self): self.client.login(username="test1", password="testaa")
self.client = APIClient() data = {"id": self.announcement.id, "title": "title0", "content": "content0",
self.url = reverse("announcement_list_api") "visible": True, "is_global": False}
user = User.objects.create(username="test") response = self.client.put(self.url, data=data)
user.set_password("testaa") self.assertEqual(response.data, {"code": 1, "data": u"至少选择一个小组"})
user.save()
def test_success_get_data(self): # 以下是公告分页的测试
def test_get_data_successfully(self):
self.client.login(username="test1", password="testaa")
self.assertEqual(self.client.get(self.url).data["code"], 0) self.assertEqual(self.client.get(self.url).data["code"], 0)
def test_keyword_announcement(self): def test_keyword_global_announcement(self):
self.client.login(username="test1", password="testaa")
Announcement.objects.create(title="aa", Announcement.objects.create(title="aa",
content="AA", content="AA",
created_by=User.objects.get(username="test"), created_by=User.objects.get(username="test1"),
visible=True) visible=True,
is_global=True)
Announcement.objects.create(title="bb", Announcement.objects.create(title="bb",
content="BB", content="BB",
created_by=User.objects.get(username="test"), created_by=User.objects.get(username="test1"),
visible=False) visible=False,
is_global=True)
response = self.client.get(self.url + "?visible=true")
self.assertEqual(response.data["code"], 0)
for item in response.data["data"]:
self.assertEqual(item["visible"], True)
def test_keyword_group_announcement(self):
self.client.login(username="test2", password="testbb")
Announcement.objects.create(title="aa",
content="AA",
created_by=User.objects.get(username="test2"),
visible=True,
is_global=False)
Announcement.objects.create(title="cc",
content="CC",
created_by=User.objects.get(username="test2"),
visible=False,
is_global=False)
response = self.client.get(self.url + "?visible=true") response = self.client.get(self.url + "?visible=true")
self.assertEqual(response.data["code"], 0) self.assertEqual(response.data["code"], 0)
@ -98,12 +152,14 @@ class AnnouncementPageTest(TestCase):
Announcement.objects.create(title="aa", Announcement.objects.create(title="aa",
content="AA", content="AA",
created_by=User.objects.get(username="test"), created_by=User.objects.get(username="test"),
visible=True) visible=True,
is_global=True)
Announcement.objects.create(title="bb", Announcement.objects.create(title="bb",
content="BB", content="BB",
created_by=User.objects.get(username="test"), created_by=User.objects.get(username="test"),
visible=False) visible=False,
is_global=True)
def test_visit_announcement_successfully(self): def test_visit_announcement_successfully(self):
response = self.client.get('/announcement/1/') response = self.client.get('/announcement/1/')
@ -112,3 +168,4 @@ class AnnouncementPageTest(TestCase):
def test_announcement_does_not_exist(self): def test_announcement_does_not_exist(self):
response = self.client.get('/announcement/3/') response = self.client.get('/announcement/3/')
self.assertTemplateUsed(response, "utils/error.html") self.assertTemplateUsed(response, "utils/error.html")

View File

@ -36,7 +36,7 @@ class AnnouncementAdminAPIView(APIView):
if request.user.admin_type == SUPER_ADMIN: if request.user.admin_type == SUPER_ADMIN:
groups = Group.objects.filter(id__in=data["groups"]) groups = Group.objects.filter(id__in=data["groups"])
else: else:
groups = Group.objects.filter(id__in=data["groups"], created_by=request.user) groups = Group.objects.filter(id__in=data["groups"], admin=request.user)
if not groups.count(): if not groups.count():
return error_response(u"至少选择一个小组") return error_response(u"至少选择一个小组")
else: else:
@ -49,7 +49,6 @@ class AnnouncementAdminAPIView(APIView):
is_global=data["is_global"]) is_global=data["is_global"])
announcement.groups.add(*groups) announcement.groups.add(*groups)
return success_response(u"公告发布成功!") return success_response(u"公告发布成功!")
else: else:
return serializer_invalid_response(serializer) return serializer_invalid_response(serializer)
@ -76,7 +75,7 @@ class AnnouncementAdminAPIView(APIView):
if request.user.admin_type == SUPER_ADMIN: if request.user.admin_type == SUPER_ADMIN:
groups = Group.objects.filter(id__in=data["groups"]) groups = Group.objects.filter(id__in=data["groups"])
else: else:
groups = Group.objects.filter(id__in=data["groups"], created_by=request.user) groups = Group.objects.filter(id__in=data["groups"], admin=request.user)
if not groups.count(): if not groups.count():
return error_response(u"至少选择一个小组") return error_response(u"至少选择一个小组")
announcement.title = data["title"] announcement.title = data["title"]

View File

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('group', '0004_merge'),
]
operations = [
migrations.CreateModel(
name='Contest',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.CharField(unique=True, max_length=40)),
('description', models.TextField()),
('mode', models.IntegerField()),
('show_rank', models.BooleanField()),
('show_user_submission', models.BooleanField()),
('password', models.CharField(max_length=30, null=True, blank=True)),
('contest_type', models.IntegerField()),
('start_time', models.DateTimeField()),
('end_time', models.DateTimeField()),
('create_time', models.DateTimeField(auto_now_add=True)),
('last_updated_time', models.DateTimeField(auto_now=True)),
('created_by', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
('groups', models.ManyToManyField(to='group.Group')),
],
options={
'db_table': 'contest',
},
),
migrations.CreateModel(
name='ContestProblem',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('title', models.CharField(max_length=50)),
('description', models.TextField()),
('input_description', models.CharField(max_length=10000)),
('output_description', models.CharField(max_length=10000)),
('samples', models.TextField(blank=True)),
('test_case_id', models.CharField(max_length=40)),
('hint', models.TextField(null=True, blank=True)),
('create_time', models.DateTimeField(auto_now_add=True)),
('time_limit', models.IntegerField()),
('memory_limit', models.IntegerField()),
('visible', models.BooleanField(default=True)),
('total_submit_number', models.IntegerField(default=0)),
('total_accepted_number', models.IntegerField(default=0)),
('sort_index', models.CharField(max_length=30)),
('contest', models.ForeignKey(to='contest.Contest')),
('created_by', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
],
options={
'db_table': 'contest_problem',
},
),
migrations.CreateModel(
name='ContestProblemTestCase',
fields=[
('id', models.CharField(max_length=40, serialize=False, primary_key=True, db_index=True)),
('score', models.IntegerField()),
('problem', models.ForeignKey(to='contest.ContestProblem')),
],
options={
'db_table': 'contest_problem_test_case',
},
),
]

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contest', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='contest',
name='visible',
field=models.BooleanField(default=True),
),
]

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contest', '0002_contest_visible'),
]
operations = [
migrations.AddField(
model_name='contestproblem',
name='difficulty',
field=models.IntegerField(default=1),
preserve_default=False,
),
]

View File

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
class Migration(migrations.Migration):
dependencies = [
('contest', '0003_contestproblem_difficulty'),
]
operations = [
migrations.RemoveField(
model_name='contestproblem',
name='difficulty',
),
]

View File

@ -3,18 +3,25 @@ from django.db import models
from account.models import User from account.models import User
from problem.models import AbstractProblem from problem.models import AbstractProblem
from group.models import Group
class Contest(models.Model): class Contest(models.Model):
title = models.CharField(max_length=40) title = models.CharField(max_length=40, unique=True)
description = models.TextField() description = models.TextField()
# 比赛模式 现在有 acm 模式,按照 ac 题目数量得分模式, # 比赛模式0 即为是acm模式1 即为是按照总的 ac 题目数量排名模式2 即为按照 ac 的题目的总分排名模式
# 按照 ac 的题目的总分得分模式和按照通过的测试用例总分得分模式等
mode = models.IntegerField() mode = models.IntegerField()
# 是否显示排名结果 # 是否显示排名结果
show_rank = models.BooleanField() show_rank = models.BooleanField()
# 如果这一项不为空,那这就不是公开赛,需要密码才能进入 # 是否显示别人的提交记录
show_user_submission = models.BooleanField()
# 只能超级管理员创建公开赛,管理员只能创建小组内部的比赛
# 如果这一项不为空,即为有密码的公开赛,没有密码的可以为小组赛或者是公开赛(此时用比赛的类型来表示)
password = models.CharField(max_length=30, blank=True, null=True) password = models.CharField(max_length=30, blank=True, null=True)
# 比赛的类型: 0 即为是小组赛1 即为是无密码的公开赛2 即为是有密码的公开赛
contest_type = models.IntegerField()
# 开始时间 # 开始时间
start_time = models.DateTimeField() start_time = models.DateTimeField()
# 结束时间 # 结束时间
@ -23,7 +30,11 @@ class Contest(models.Model):
create_time = models.DateTimeField(auto_now_add=True) create_time = models.DateTimeField(auto_now_add=True)
# 最后修改时间 # 最后修改时间
last_updated_time = models.DateTimeField(auto_now=True) last_updated_time = models.DateTimeField(auto_now=True)
# 这个比赛是谁创建的
created_by = models.ForeignKey(User) created_by = models.ForeignKey(User)
groups = models.ManyToManyField(Group)
# 是否可见 false的话相当于删除
visible = models.BooleanField(default=True)
class Meta: class Meta:
db_table = "contest" db_table = "contest"

105
contest/serializers.py Normal file
View File

@ -0,0 +1,105 @@
# coding=utf-8
import json
from rest_framework import serializers
from account.models import User
from account.serializers import UserSerializer
from .models import Contest, ContestProblem
class CreateContestSerializer(serializers.Serializer):
title = serializers.CharField(max_length=40)
description = serializers.CharField(max_length=5000)
mode = serializers.IntegerField()
contest_type = serializers.IntegerField()
show_rank = serializers.BooleanField()
show_user_submission = serializers.BooleanField()
password = serializers.CharField(max_length=30, required=False, default=None)
start_time = serializers.DateTimeField()
end_time = serializers.DateTimeField()
groups = serializers.ListField(child=serializers.IntegerField(), required=False, default=[])
visible = serializers.BooleanField()
class ContestSerializer(serializers.ModelSerializer):
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["username"]
created_by = UserSerializer()
class Meta:
model = Contest
class EditContestSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=40)
description = serializers.CharField(max_length=10000)
mode = serializers.IntegerField()
contest_type = serializers.IntegerField()
show_rank = serializers.BooleanField()
show_user_submission = serializers.BooleanField()
password = serializers.CharField(max_length=30, required=False, default=None)
start_time = serializers.DateTimeField()
end_time = serializers.DateTimeField()
groups = serializers.ListField(child=serializers.IntegerField(), required=False, default=[])
visible = serializers.BooleanField()
class ContestProblemSampleSerializer(serializers.ListField):
input = serializers.CharField(max_length=3000)
output = serializers.CharField(max_length=3000)
class JSONField(serializers.Field):
def to_representation(self, value):
return json.loads(value)
class CreateContestProblemSerializer(serializers.Serializer):
contest_id = serializers.IntegerField()
title = serializers.CharField(max_length=50)
description = serializers.CharField(max_length=10000)
input_description = serializers.CharField(max_length=10000)
output_description = serializers.CharField(max_length=10000)
# [{"input": "1 1", "output": "2"}]
samples = ContestProblemSampleSerializer()
test_case_id = serializers.CharField(max_length=40)
time_limit = serializers.IntegerField()
memory_limit = serializers.IntegerField()
hint = serializers.CharField(max_length=3000, allow_blank=True)
sort_index = serializers.CharField(max_length=30)
class ContestProblemSerializer(serializers.ModelSerializer):
class ContestSerializer(serializers.ModelSerializer):
class Meta:
model = Contest
fields = ["title", "id"]
samples = JSONField()
contest = ContestSerializer()
created_by = UserSerializer()
class Meta:
model = ContestProblem
class EditContestProblemSerializer(serializers.Serializer):
id = serializers.IntegerField()
title = serializers.CharField(max_length=50)
description = serializers.CharField(max_length=10000)
input_description = serializers.CharField(max_length=10000)
output_description = serializers.CharField(max_length=10000)
test_case_id = serializers.CharField(max_length=40)
time_limit = serializers.IntegerField()
memory_limit = serializers.IntegerField()
samples = ContestProblemSampleSerializer()
hint = serializers.CharField(max_length=3000, allow_blank=True)
visible = serializers.BooleanField()
sort_index = serializers.CharField(max_length=30)

View File

@ -1,3 +1,336 @@
# coding=utf-8
import json
from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
# Create your tests here. from rest_framework.test import APITestCase, APIClient
from account.models import User
from group.models import Group
from contest.models import Contest, ContestProblem
from announcement.models import Announcement
from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN
class ContestAdminAPITest(APITestCase):
def setUp(self):
self.client = APIClient()
self.url = reverse('contest_admin_api')
user1 = User.objects.create(username="test1", admin_type=SUPER_ADMIN)
user1.set_password("testaa")
user1.save()
user2 = User.objects.create(username="test2", admin_type=ADMIN)
user2.set_password("testbb")
user2.save()
user3 = User.objects.create(username="test3", admin_type=REGULAR_USER)
user3.set_password("testcc")
user3.save()
self.group = Group.objects.create(name="group1", description="des0",
join_group_setting=0, visible=True,
admin=user2)
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
contest_type=2, show_rank=True, show_user_submission=True,
start_time="2015-08-15T10:00:00.000Z",
end_time="2015-08-15T12:00:00.000Z",
password="aacc", created_by=User.objects.get(username="test1"))
self.group_contest = Contest.objects.create(title="titley", description="descriptiony", mode=1,
contest_type=2, show_rank=True, show_user_submission=True,
start_time="2015-08-15T10:00:00.000Z",
end_time="2015-08-15T12:00:00.000Z",
password="aacc", created_by=User.objects.get(username="test1"))
# 以下是比赛发布的测试
def test_invalid_format(self):
self.client.login(username="test1", password="testaa")
data = {"title": "test1"}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_global_contest_does_not_has_privileges(self):
self.client.login(username="test2", password="testbb")
data = {"title": "title0", "description": "description0", "mode": 1, "contest_type": 2,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "password": "aabb", "visible": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"只有超级管理员才可创建公开赛"})
def test_global_contest_password_exists(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title0", "description": "description0", "mode": 1, "contest_type": 2,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "visible": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"此比赛为有密码的公开赛,密码不可为空"})
def test_group_contest_group_at_least_one(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title0", "description": "description0", "mode": 1, "contest_type": 0,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "visible": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"请至少选择一个小组"})
def test_global_contest_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title1", "description": "description1", "mode": 1, "contest_type": 2,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "password": "aabb", "visible": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 0)
def test_group_contest_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title3", "description": "description3", "mode": 1, "contest_type": 0,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "groups": [self.group.id], "visible": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 0)
def test_time_error(self):
self.client.login(username="test1", password="testaa")
data = {"title": "title2", "description": "description2", "mode": 1, "contest_type": 2,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T12:00:00.000Z",
"end_time": "2015-08-15T10:00:00.000Z", "password": "aabb", "visible": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"比赛的开始时间不能晚于或等于比赛结束的时间"})
def test_contest_has_exists(self):
self.client.login(username="test1", password="testaa")
data = {"title": "titlex", "description": "descriptionx", "mode": 1, "contest_type": 2,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "password": "aabb", "visible": True}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"比赛名已经存在"})
# 以下是编辑比赛的测试
def test_put_invalid_data(self):
self.client.login(username="test1", password="testaa")
data = {"title": "test0", "description": "description0"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_contest_does_not_exist(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.global_contest.id + 10, "title": "title2", "description": "description2", "mode": 1,
"contest_type": 2, "show_rank": True, "show_user_submission": True,
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T12:00:00.000Z", "password": "aabb",
"visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"该比赛不存在!"})
def test_edit_global_contest_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.global_contest.id, "title": "titlez", "description": "descriptionz", "mode": 1,
"contest_type": 2, "show_rank": True, "show_user_submission": True,
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T13:00:00.000Z", "password": "aabb",
"visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
self.assertEqual(response.data["data"]["title"], "titlez")
self.assertEqual(response.data["data"]["end_time"], "2015-08-15T13:00:00Z")
def test_edit_group_contest_successfully(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.group_contest.id, "title": "titleyyy", "description": "descriptionyyyy", "mode": 1,
"contest_type": 0, "show_rank": True, "show_user_submission": True,
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T13:00:00.000Z",
"groups": [self.group.id], "visible": False}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
self.assertEqual(response.data["data"]["title"], "titleyyy")
self.assertEqual(response.data["data"]["end_time"], "2015-08-15T13:00:00Z")
self.assertEqual(response.data["data"]["visible"], False)
def test_edit_group_at_least_one(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.group_contest.id, "title": "titleyyy", "description": "descriptionyyyy", "mode": 1,
"contest_type": 0, "show_rank": True, "show_user_submission": True,
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T13:00:00.000Z", "visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"请至少选择一个小组"})
def test_edit_contest_has_exists(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.global_contest.id, "title": "titley", "description": "descriptiony", "mode": 1,
"contest_type": 2, "show_rank": True, "show_user_submission": True,
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T12:00:00.000Z", "password": "aabb",
"visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"该比赛名称已经存在"})
def test_edit_global_contest_does_not_has_privileges(self):
self.client.login(username="test2", password="testbb")
data = {"id": self.global_contest.id, "title": "titlexxxxxxxxx", "description": "descriptionxxxxxx", "mode": 1,
"contest_type": 2, "show_rank": True, "show_user_submission": True,
"start_time": "2015-08-15T10:00:00.000Z", "end_time": "2015-08-15T12:00:00.000Z", "password": "aabb",
"visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"只有超级管理员才可创建公开赛"})
def test_edit_global_contest_password_exists(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.global_contest.id, "title": "title0", "description": "description0", "mode": 1, "contest_type": 2,
"show_rank": True, "show_user_submission": True, "start_time": "2015-08-15T10:00:00.000Z",
"end_time": "2015-08-15T12:00:00.000Z", "visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"此比赛为有密码的公开赛,密码不可为空"})
def test_edit_time_error(self):
self.client.login(username="test1", password="testaa")
data = {"id": self.global_contest.id, "title": "titleaaaa", "description": "descriptionaaaaa", "mode": 1,
"contest_type": 2, "show_rank": True, "show_user_submission": True,
"start_time": "2015-08-15T12:00:00.000Z", "end_time": "2015-08-15T10:00:00.000Z", "password": "aabb",
"visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"比赛的开始时间不能晚于或等于比赛结束的时间"})
# 以下是比赛分页的测试
def test_get_data_successfully(self):
self.client.login(username="test1", password="testaa")
self.assertEqual(self.client.get(self.url).data["code"], 0)
def test_keyword_contest(self):
self.client.login(username="test1", password="testaa")
response = self.client.get(self.url + "?visible=true")
self.assertEqual(response.data["code"], 0)
for item in response.data["data"]:
self.assertEqual(item["visible"], True)
def test_query_by_keyword(self):
self.client.login(username="test1", password="testaa")
response = self.client.get(self.url + "?keyword=title1")
self.assertEqual(response.data["code"], 0)
class ContestProblemAdminAPItEST(APITestCase):
def setUp(self):
self.client = APIClient()
self.url = reverse('contest_problem_admin_api')
self.user = User.objects.create(username="test1", admin_type=SUPER_ADMIN)
self.user.set_password("testaa")
self.user.save()
self.client.login(username="test1", password="testaa")
self.global_contest = Contest.objects.create(title="titlex", description="descriptionx", mode=1,
contest_type=2, show_rank=True, show_user_submission=True,
start_time="2015-08-15T10:00:00.000Z",
end_time="2015-08-15T12:00:00.000Z",
password="aacc", created_by=User.objects.get(username="test1"))
self. contest_problem = ContestProblem.objects.create(title="titlex",
description="descriptionx",
input_description="input1_description",
output_description="output1_description",
test_case_id="1",
samples=json.dumps([{"input": "1 1", "output": "2"}]),
time_limit=100,
memory_limit=1000,
hint="hint1",
created_by=User.objects.get(username="test1"),
contest=Contest.objects.get(title="titlex"),
sort_index="a")
# 以下是发布比赛题目的测试
def test_invalid_format(self):
data = {"title": "test1"}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_release_contest_problem_successfully(self):
data = {"title": "title2",
"description": "description2",
"input_description": "input_description2",
"output_description": "output_description2",
"test_case_id": "1",
"source": "source1",
"samples": [{"input": "1 1", "output": "2"}],
"time_limit": "100",
"memory_limit": "1000",
"hint": "hint1",
"sort_index": "b",
"contest_id": self.global_contest.id}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data["code"], 0)
def test_contest_does_not_exists(self):
data = {"title": "titlezzzzzzzz",
"description": "descriptionzzzzzzzzzzz",
"input_description": "input_description2",
"output_description": "output_description2",
"test_case_id": "1",
"source": "source1",
"samples": [{"input": "1 1", "output": "2"}],
"time_limit": "100",
"memory_limit": "1000",
"hint": "hint1",
"sort_index": "b",
"contest_id": self.global_contest.id + 10}
response = self.client.post(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"比赛不存在"})
# 以下是编辑比赛题目的测试
def test_invalid_data(self):
data = {"title": "test1"}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 1)
def test_edit_problem_does_not_exist(self):
data = {"id": self.contest_problem.id + 1,
"title": "title2",
"description": "description2",
"input_description": "input_description2",
"output_description": "output_description2",
"test_case_id": "1",
"source": "source1",
"samples": [{"input": "1 1", "output": "2"}],
"time_limit": "100",
"memory_limit": "1000",
"hint": "hint1",
"sort_index": "b",
"visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"该比赛题目不存在!"})
def test_edit_problem_successfully(self):
data = {"id": self.contest_problem.id,
"title": "title2222222",
"description": "description22222222",
"input_description": "input_description2",
"output_description": "output_description2",
"test_case_id": "1",
"source": "source1",
"samples": [{"input": "1 1", "output": "2"}],
"time_limit": "100",
"memory_limit": "1000",
"hint": "hint1",
"sort_index": "b",
"visible": True}
response = self.client.put(self.url, data=data)
self.assertEqual(response.data["code"], 0)
# 以下是比赛题目分页的测试
def test_get_data_successfully(self):
self.client.login(username="test1", password="testaa")
self.assertEqual(self.client.get(self.url).data["code"], 0)
def test_keyword_contest(self):
self.client.login(username="test1", password="testaa")
response = self.client.get(self.url + "?visible=true")
self.assertEqual(response.data["code"], 0)
for item in response.data["data"]:
self.assertEqual(item["visible"], True)
def test_query_by_keyword(self):
self.client.login(username="test1", password="testaa")
response = self.client.get(self.url + "?keyword=title1")
self.assertEqual(response.data["code"], 0)
def test_query_contest_problem_does_not_exist(self):
data = {"contest_problem_id": 1000000}
response = self.client.get(self.url, data=data)
self.assertEqual(response.data, {"code": 1, "data": u"比赛题目不存在"})
def test_query_contest_problem_exists(self):
data = {"contest_problem_id": self.contest_problem.id}
response = self.client.get(self.url, data=data)
self.assertEqual(response.data["code"], 0)

View File

@ -1,3 +1,223 @@
# coding=utf-8
import json
from django.shortcuts import render from django.shortcuts import render
from django.db import IntegrityError
from django.utils import dateparse
from django.db.models import Q
from rest_framework.views import APIView
from utils.shortcuts import (serializer_invalid_response, error_response,
success_response, paginate, rand_str, error_page)
# Create your views here. from account.models import REGULAR_USER, ADMIN, SUPER_ADMIN
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
class ContestAdminAPIView(APIView):
def post(self, request):
"""
比赛发布json api接口
---
request_serializer: CreateContestSerializer
response_serializer: ContestSerializer
"""
serializer = CreateContestSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
groups = []
# 首先判断比赛的类型: 0 即为是小组赛1 即为是无密码的公开赛2 即为是有密码的公开赛
# 此时为有密码的公开赛,并且此时只能超级管理员才有权限此创建比赛
if data["contest_type"] in [1, 2]:
if request.user.admin_type != SUPER_ADMIN:
return error_response(u"只有超级管理员才可创建公开赛")
if data["contest_type"] == 2:
if not data["password"]:
return error_response(u"此比赛为有密码的公开赛,密码不可为空")
# 没有密码的公开赛 没有密码的小组赛
elif data["contest_type"] == 0:
if request.user.admin_type == SUPER_ADMIN:
groups = Group.objects.filter(id__in=data["groups"])
else:
groups = Group.objects.filter(id__in=data["groups"], admin=request.user)
if not groups.count():
return error_response(u"请至少选择一个小组")
if data["start_time"] >= data["end_time"]:
return error_response(u"比赛的开始时间不能晚于或等于比赛结束的时间")
try:
contest = Contest.objects.create(title=data["title"], description=data["description"],
mode=data["mode"], contest_type=data["contest_type"],
show_rank=data["show_rank"], password=data["password"],
show_user_submission=data["show_user_submission"],
start_time=dateparse.parse_datetime(data["start_time"]),
end_time=dateparse.parse_datetime(data["end_time"]),
created_by=request.user, visible=data["visible"])
except IntegrityError:
return error_response(u"比赛名已经存在")
contest.groups.add(*groups)
return success_response(ContestSerializer(contest).data)
else:
return serializer_invalid_response(serializer)
def put(self, request):
"""
比赛编辑json api接口
---
request_serializer: EditContestSerializer
response_serializer: ContestSerializer
"""
serializer = EditContestSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
groups = []
try:
contest = Contest.objects.get(id=data["id"])
except Contest.DoesNotExist:
return error_response(u"该比赛不存在!")
try:
contest = Contest.objects.get(title=data["title"])
if contest.id != data["id"]:
return error_response(u"该比赛名称已经存在")
except Contest.DoesNotExist:
pass
if data["contest_type"] in [1, 2]:
if request.user.admin_type != SUPER_ADMIN:
return error_response(u"只有超级管理员才可创建公开赛")
if data["contest_type"] == 2:
if not data["password"]:
return error_response(u"此比赛为有密码的公开赛,密码不可为空")
elif data["contest_type"] == 0:
if request.user.admin_type == SUPER_ADMIN:
groups = Group.objects.filter(id__in=data["groups"])
else:
groups = Group.objects.filter(id__in=data["groups"], admin=request.user)
if not groups.count():
return error_response(u"请至少选择一个小组")
if data["start_time"] >= data["end_time"]:
return error_response(u"比赛的开始时间不能晚于或等于比赛结束的时间")
contest.title = data["title"]
contest.description = data["description"]
contest.mode = data["mode"]
contest.contest_type = data["contest_type"]
contest.show_rank = data["show_rank"]
contest.show_user_submission = data["show_user_submission"]
contest.start_time = dateparse.parse_datetime(data["start_time"])
contest.end_time = dateparse.parse_datetime(data["end_time"])
contest.visible = data["visible"]
contest.password = data["password"]
contest.save()
contest.groups.clear()
contest.groups.add(*groups)
return success_response(ContestSerializer(contest).data)
else:
return serializer_invalid_response(serializer)
def get(self, request):
"""
比赛分页json api接口
---
response_serializer: ContestSerializer
"""
contest = Contest.objects.all().order_by("-last_updated_time")
visible = request.GET.get("visible", None)
if visible:
contest = contest.filter(visible=(visible == "true"))
keyword = request.GET.get("keyword", None)
if keyword:
contest = contest.filter(Q(title__contains=keyword) |
Q(description__contains=keyword))
return paginate(request, contest, ContestSerializer)
class ContestProblemAdminAPIView(APIView):
def post(self, request):
"""
比赛题目发布json api接口
---
request_serializer: CreateContestProblemSerializer
response_serializer: ContestProblemSerializer
"""
serializer = CreateContestProblemSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
try:
contest = Contest.objects.get(id=data["contest_id"])
except Contest.DoesNotExist:
return error_response(u"比赛不存在")
contest_problem = ContestProblem.objects.create(title=data["title"],
description=data["description"],
input_description=data["input_description"],
output_description=data["output_description"],
test_case_id=data["test_case_id"],
samples=json.dumps(data["samples"]),
time_limit=data["time_limit"],
memory_limit=data["memory_limit"],
created_by=request.user,
hint=data["hint"],
contest=contest,
sort_index=data["sort_index"])
return success_response(ContestProblemSerializer(contest_problem).data)
else:
return serializer_invalid_response(serializer)
def put(self, request):
"""
比赛题目编辑json api接口
---
request_serializer: EditContestProblemSerializer
response_serializer: ContestProblemSerializer
"""
serializer = EditContestProblemSerializer(data=request.data)
if serializer.is_valid():
data = serializer.data
try:
contest_problem = ContestProblem.objects.get(id=data["id"])
except ContestProblem.DoesNotExist:
return error_response(u"该比赛题目不存在!")
contest_problem.title = data["title"]
contest_problem.description = data["description"]
contest_problem.input_description = data["input_description"]
contest_problem.output_description = data["output_description"]
contest_problem.test_case_id = data["test_case_id"]
contest_problem.time_limit = data["time_limit"]
contest_problem.memory_limit = data["memory_limit"]
contest_problem.samples = json.dumps(data["samples"])
contest_problem.hint = data["hint"]
contest_problem.visible = data["visible"]
contest_problem.sort_index = data["sort_index"]
contest_problem.save()
return success_response(ContestProblemSerializer(contest_problem).data)
else:
return serializer_invalid_response(serializer)
def get(self, request):
"""
比赛题目分页json api接口
---
response_serializer: ProblemSerializer
"""
contest_problem_id = request.GET.get("contest_problem_id", None)
if contest_problem_id:
try:
contest_problem = ContestProblem.objects.get(id=contest_problem_id)
return success_response(ContestProblemSerializer(contest_problem).data)
except ContestProblem.DoesNotExist:
return error_response(u"比赛题目不存在")
contest_problem = ContestProblem.objects.all().order_by("sort_index")
visible = request.GET.get("visible", None)
if visible:
contest_problem = contest_problem.filter(visible=(visible == "true"))
keyword = request.GET.get("keyword", None)
if keyword:
contest_problem = contest_problem.filter(Q(title__contains=keyword) |
Q(description__contains=keyword))
return paginate(request, contest_problem, ContestProblemSerializer)

View File

@ -226,7 +226,8 @@ class JoinGroupRequestAdminAPIView(APIView, GroupAPIViewBase):
if serializer.is_valid(): if serializer.is_valid():
data = serializer.data data = serializer.data
try: try:
join_request = JoinGroupRequest.objects.get(id=data["request_id"], group__admin=request.user, status=False) join_request = JoinGroupRequest.objects.get(id=data["request_id"], group__admin=request.user,
status=False)
except JoinGroupRequest.DoesNotExist: except JoinGroupRequest.DoesNotExist:
return error_response(u"请求不存在") return error_response(u"请求不存在")

View File

@ -52,6 +52,7 @@ INSTALLED_APPS = (
'problem', 'problem',
'admin', 'admin',
'submission', 'submission',
'contest',
'rest_framework', 'rest_framework',
'rest_framework_swagger', 'rest_framework_swagger',
@ -156,3 +157,8 @@ LOGGING = {
} }
}, },
} }
REST_FRAMEWORK = {
'TEST_REQUEST_DEFAULT_FORMAT': 'json'
}

View File

@ -8,6 +8,8 @@ from account.views import (UserLoginAPIView, UsernameCheckAPIView, UserRegisterA
UserAdminAPIView, UserInfoAPIView) UserAdminAPIView, UserInfoAPIView)
from announcement.views import AnnouncementAdminAPIView from announcement.views import AnnouncementAdminAPIView
from contest.views import ContestAdminAPIView, ContestProblemAdminAPIView
from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView, from group.views import (GroupAdminAPIView, GroupMemberAdminAPIView,
JoinGroupAPIView, JoinGroupRequestAdminAPIView) JoinGroupAPIView, JoinGroupRequestAdminAPIView)
@ -35,6 +37,7 @@ urlpatterns = [
url(r'^api/username_check/$', UsernameCheckAPIView.as_view(), name="username_check_api"), url(r'^api/username_check/$', UsernameCheckAPIView.as_view(), name="username_check_api"),
url(r'^api/email_check/$', EmailCheckAPIView.as_view(), name="email_check_api"), url(r'^api/email_check/$', EmailCheckAPIView.as_view(), name="email_check_api"),
url(r'^api/admin/announcement/$', AnnouncementAdminAPIView.as_view(), name="announcement_admin_api"), url(r'^api/admin/announcement/$', AnnouncementAdminAPIView.as_view(), name="announcement_admin_api"),
url(r'^api/admin/contest/$', ContestAdminAPIView.as_view(), name="contest_admin_api"),
url(r'^api/admin/user/$', UserAdminAPIView.as_view(), name="user_admin_api"), url(r'^api/admin/user/$', UserAdminAPIView.as_view(), name="user_admin_api"),
url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"), url(r'^problem/(?P<problem_id>\d+)/$', "problem.views.problem_page", name="problem_page"),
url(r'^announcement/(?P<announcement_id>\d+)/$', "announcement.views.announcement_page", url(r'^announcement/(?P<announcement_id>\d+)/$', "announcement.views.announcement_page",
@ -49,6 +52,7 @@ urlpatterns = [
url(r'^api/admin/group_member/$', GroupMemberAdminAPIView.as_view(), name="group_member_admin_api"), url(r'^api/admin/group_member/$', GroupMemberAdminAPIView.as_view(), name="group_member_admin_api"),
url(r'^api/admin/group_join/$', JoinGroupAPIView.as_view(), name="group_join_admin_api"), url(r'^api/admin/group_join/$', JoinGroupAPIView.as_view(), name="group_join_admin_api"),
url(r'^api/admin/problem/$', ProblemAdminAPIView.as_view(), name="problem_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/test_case_upload/$', TestCaseUploadAPIView.as_view(), name="test_case_upload_api"), 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/tag/$', ProblemTagAdminAPIView.as_view(), name="problem_tag_admin_api"),
url(r'^problem/(?P<problem_id>\d+)/my_submissions/$', "submission.views.problem_my_submissions_list_page", url(r'^problem/(?P<problem_id>\d+)/my_submissions/$', "submission.views.problem_my_submissions_list_page",

View File

@ -32,8 +32,6 @@ class AbstractProblem(models.Model):
# last_update_time = models.DateTimeField(auto_now=True) # last_update_time = models.DateTimeField(auto_now=True)
# 这个题是谁创建的 # 这个题是谁创建的
created_by = models.ForeignKey(User) created_by = models.ForeignKey(User)
# 来源
source = models.CharField(max_length=30, blank=True, null=True)
# 时间限制 单位是毫秒 # 时间限制 单位是毫秒
time_limit = models.IntegerField() time_limit = models.IntegerField()
# 内存限制 单位是MB # 内存限制 单位是MB
@ -54,3 +52,5 @@ class Problem(AbstractProblem):
difficulty = models.IntegerField() difficulty = models.IntegerField()
# 标签 # 标签
tags = models.ManyToManyField(ProblemTag) tags = models.ManyToManyField(ProblemTag)
# 来源
source = models.CharField(max_length=30, blank=True, null=True)

View File

@ -1,7 +1,7 @@
# coding=utf-8 # coding=utf-8
import json import json
from django.test import TestCase from django.test import TestCase, Client
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from rest_framework.test import APITestCase, APIClient from rest_framework.test import APITestCase, APIClient
@ -39,7 +39,6 @@ class ProblemPageTest(TestCase):
self.assertTemplateUsed(response, "utils/error.html") self.assertTemplateUsed(response, "utils/error.html")
class ProblemAdminTest(APITestCase): class ProblemAdminTest(APITestCase):
def _create_data(self, problem_id, visible, tags): def _create_data(self, problem_id, visible, tags):
data = {"id": problem_id, data = {"id": problem_id,
@ -164,3 +163,29 @@ class ProblemTagAdminAPITest(APITestCase):
def test_get_all_problem_tag_successfully(self): def test_get_all_problem_tag_successfully(self):
self.assertEqual(self.client.get(self.url).data["code"], 0) self.assertEqual(self.client.get(self.url).data["code"], 0)
class ProblemListPageTest(TestCase):
def setUp(self):
self.client = Client()
self.url = reverse('problem_list_page', kwargs={"page": 1})
self.user = User.objects.create(username="test", admin_type=SUPER_ADMIN)
self.user.set_password("testaa")
self.user.save()
self.client.login(username="test", password="testaa")
ProblemTag.objects.create(name="tag1")
ProblemTag.objects.create(name="tag2")
self.problem = Problem.objects.create(title="title1",
description="description1",
input_description="input1_description",
output_description="output1_description",
test_case_id="1",
source="source1",
samples=json.dumps([{"input": "1 1", "output": "2"}]),
time_limit=100,
memory_limit=1000,
difficulty=1,
hint="hint1",
created_by=User.objects.get(username="test"))

View File

@ -57,7 +57,6 @@ class ProblemAdminAPIView(APIView):
difficulty=data["difficulty"], difficulty=data["difficulty"],
created_by=request.user, created_by=request.user,
hint=data["hint"]) hint=data["hint"])
for tag in data["tags"]: for tag in data["tags"]:
try: try:
tag = ProblemTag.objects.get(name=tag) tag = ProblemTag.objects.get(name=tag)

View File

@ -69,6 +69,22 @@ li.list-group-item {
padding: 0 0; padding: 0 0;
} }
.ac-flag{ .ac-flag {
color: green; color: green;
}
.CodeMirror{
min-height: 250px;
_height:250px;
height: auto;
}
.CodeMirror-scroll {
overflow: auto;
min-height: 250px;
_height:250px;
height: auto;
position: relative;
outline: none;
} }

View File

@ -4,7 +4,7 @@
<div class="container main"> <div class="container main">
<ul class="nav nav-tabs nav-tabs-google"> <ul class="nav nav-tabs nav-tabs-google">
<li role="presentation" class="active"> <li role="presentation" class="active">
<a href="problem.html">题目</a></li> <a href="/problem/{{ problem.id }}/">题目</a></li>
<li role="presentation"><a href="/problem/{{ problem.id }}/my_submissions/">我的提交</a></li> <li role="presentation"><a href="/problem/{{ problem.id }}/my_submissions/">我的提交</a></li>
</ul> </ul>
{% include "oj/problem/_problem_header.html" %} {% include "oj/problem/_problem_header.html" %}