mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 08:23:20 +00:00
Merge branch 'dev' into dev-sxw
添加了后台比赛管理的api
This commit is contained in:
commit
176c91061a
@ -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
|
||||||
|
@ -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=[])
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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"]
|
||||||
|
74
contest/migrations/0001_initial.py
Normal file
74
contest/migrations/0001_initial.py
Normal 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',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
19
contest/migrations/0002_contest_visible.py
Normal file
19
contest/migrations/0002_contest_visible.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
20
contest/migrations/0003_contestproblem_difficulty.py
Normal file
20
contest/migrations/0003_contestproblem_difficulty.py
Normal 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,
|
||||||
|
),
|
||||||
|
]
|
18
contest/migrations/0004_remove_contestproblem_difficulty.py
Normal file
18
contest/migrations/0004_remove_contestproblem_difficulty.py
Normal 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',
|
||||||
|
),
|
||||||
|
]
|
@ -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
105
contest/serializers.py
Normal 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)
|
||||||
|
|
||||||
|
|
335
contest/tests.py
335
contest/tests.py
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
222
contest/views.py
222
contest/views.py
@ -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)
|
@ -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"请求不存在")
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
}
|
@ -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",
|
||||||
|
@ -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)
|
||||||
|
@ -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"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -72,3 +72,19 @@ li.list-group-item {
|
|||||||
.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;
|
||||||
|
|
||||||
|
}
|
@ -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" %}
|
||||||
|
Loading…
Reference in New Issue
Block a user