From 44be61dab6b21553367ea84f60f40e31cb587bf4 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Wed, 5 Aug 2015 08:43:15 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=20runtest.sh=EF=BC=8C?= =?UTF-8?q?=E5=8F=AA=E6=9C=89=E5=9C=A8=E6=B5=8B=E8=AF=95=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E7=9A=84=E6=83=85=E5=86=B5=E4=B8=8B=E6=89=8D=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=E8=A6=86=E7=9B=96=E7=8E=87=E5=88=86=E6=9E=90?= =?UTF-8?q?=E5=92=8C=E6=89=93=E5=BC=80=E7=BB=93=E6=9E=9C=E9=A1=B5=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/runtest.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/runtest.sh b/tools/runtest.sh index 87399cc..f41a02b 100644 --- a/tools/runtest.sh +++ b/tools/runtest.sh @@ -1,4 +1,7 @@ #!/usr/bin/env bash coverage run --source='.' manage.py test -coverage html -open htmlcov/index.html +test_result=$? +if [ "$test_result" -eq 0 ];then + coverage html + open htmlcov/index.html +fi From 8a6093d6457c1e5ddbeacf87575a95fa4ce1d222 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Wed, 5 Aug 2015 08:44:28 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E5=88=86=E9=A1=B5=E5=87=BD=E6=95=B0=E5=92=8C=E5=AF=B9=E5=BA=94?= =?UTF-8?q?=E7=9A=84=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oj/settings.py | 1 + utils/shortcuts.py | 49 ++++++++++++++++++++++++++++++++++- utils/test_urls.py | 9 +++++++ utils/tests.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 utils/test_urls.py create mode 100644 utils/tests.py diff --git a/oj/settings.py b/oj/settings.py index db9ea8f..793f605 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -47,6 +47,7 @@ INSTALLED_APPS = ( 'django.contrib.staticfiles', 'account', + 'utils', 'rest_framework', 'rest_framework_swagger', diff --git a/utils/shortcuts.py b/utils/shortcuts.py index bd5f286..3d37063 100644 --- a/utils/shortcuts.py +++ b/utils/shortcuts.py @@ -1,4 +1,7 @@ # coding=utf-8 +from django.core.paginator import Paginator + +from rest_framework import pagination from rest_framework.response import Response @@ -11,4 +14,48 @@ def serializer_invalid_response(serializer): def success_response(data): - return Response(data={"code": 0, "data": data}) \ No newline at end of file + return Response(data={"code": 0, "data": data}) + + +def paginate(request, query_set, object_serializer): + """ + 用于分页的函数 + :param query_set 数据库查询结果 + :param object_serializer: 序列化单个object的serializer + :return response + """ + need_paginate = request.GET.get("paging", None) + # 如果请求的参数里面没有paging=true的话 就返回全部数据 + if need_paginate != "true": + return success_response(data=object_serializer(query_set, many=True).data) + + page_size = request.GET.get("page_size", None) + if not page_size: + return error_response(u"参数错误") + + try: + page_size = int(page_size) + except Exception: + return error_response(u"参数错误") + + paginator = Paginator(query_set, page_size) + page = request.GET.get("page", None) + + try: + current_page = paginator.page(page) + except Exception: + return error_response(u"参数错误") + + data = {"results": object_serializer(current_page, many=True).data, "previous_page": None, "next_page": None} + + try: + data["previous_page"] = current_page.previous_page_number() + except Exception: + pass + + try: + data["next_page"] = current_page.next_page_number() + except Exception: + pass + + return success_response(data) \ No newline at end of file diff --git a/utils/test_urls.py b/utils/test_urls.py new file mode 100644 index 0000000..0500d16 --- /dev/null +++ b/utils/test_urls.py @@ -0,0 +1,9 @@ +# coding=utf-8 +from django.conf.urls import include, url + + + +urlpatterns = [ + url(r'^paginate_test/$', "utils.tests.pagination_test_func"), +] + diff --git a/utils/tests.py b/utils/tests.py new file mode 100644 index 0000000..9ab31f9 --- /dev/null +++ b/utils/tests.py @@ -0,0 +1,64 @@ +# coding=utf-8 +from rest_framework.test import APIClient, APITestCase +from rest_framework import serializers +from rest_framework.decorators import api_view + +from account.models import User +from .shortcuts import paginate + + +class PaginationTestSerialiser(serializers.Serializer): + username = serializers.CharField(max_length=100) + + +@api_view(["GET"]) +def pagination_test_func(request): + return paginate(request, User.objects.all(), PaginationTestSerialiser) + + +class PaginatorTest(APITestCase): + urls = "utils.test_urls" + + def setUp(self): + self.client = APIClient() + self.url = "/paginate_test/" + User.objects.create(username="test1") + User.objects.create(username="test2") + + def test_no_paginate(self): + response = self.client.get(self.url) + self.assertEqual(response.data["code"], 0) + self.assertNotIn("next_page", response.data["data"]) + self.assertNotIn("previous_page", response.data["data"]) + + def test_error_parameter(self): + response = self.client.get(self.url + "?paging=true") + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) + + response = self.client.get(self.url + "?paging=true&limit=-1") + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) + + response = self.client.get(self.url + "?paging=true&limit=aa") + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) + + response = self.client.get(self.url + "?paging=true&limit=1&page_size=1&page=-1") + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) + + response = self.client.get(self.url + "?paging=true&limit=1&page_size=aaa&page=1") + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) + + response = self.client.get(self.url + "?paging=true&limit=1&page_size=1&page=aaa") + self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) + + def test_correct_paginate(self): + response = self.client.get(self.url + "?paging=true&limit=1&page_size=1&page=1") + self.assertEqual(response.data["code"], 0) + self.assertEqual(response.data["data"]["previous_page"], None) + self.assertEqual(response.data["data"]["next_page"], 2) + self.assertEqual(len(response.data["data"]["results"]), 1) + + response = self.client.get(self.url + "?paging=true&limit=1&page_size=2&page=1") + self.assertEqual(response.data["code"], 0) + self.assertEqual(response.data["data"]["previous_page"], None) + self.assertEqual(response.data["data"]["next_page"], None) + self.assertEqual(len(response.data["data"]["results"]), 2) From 5558600792c66135e97d349e1ee2d88a1324fb4b Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Wed, 5 Aug 2015 08:53:39 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E8=A1=A5=E5=85=85=E9=80=9A=E7=94=A8?= =?UTF-8?q?=E5=88=86=E9=A1=B5=E5=87=BD=E6=95=B0=E7=9A=84=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E5=92=8C=E7=94=A8=E6=B3=95=EF=BC=9B=E4=BF=AE=E6=94=B9=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E7=9A=84=E6=B5=8B=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- utils/shortcuts.py | 26 +++++++++++++++++++++++++- utils/tests.py | 10 +++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/utils/shortcuts.py b/utils/shortcuts.py index 3d37063..852622f 100644 --- a/utils/shortcuts.py +++ b/utils/shortcuts.py @@ -1,7 +1,6 @@ # coding=utf-8 from django.core.paginator import Paginator -from rest_framework import pagination from rest_framework.response import Response @@ -20,6 +19,31 @@ def success_response(data): def paginate(request, query_set, object_serializer): """ 用于分页的函数 + 如果 url 里面不含有paging=true,那么将返回全部数据。类似 + [ + { + "username": "1111111", + "password": "123456" + } + ] + 如果 url 中有 paging=true 的参数, + 然后还需要读取其余的两个参数,page=[int],需要的页码,p + age_size=[int],一页的数据条数 + 参数错误的时候,返回{"code": 1, "data": u"参数错误"} + 返回的数据格式 + { + "code": 0, + "data": { + "previous_page": null, + "results": [ + { + "username": "1111111", + "password": "123456" + } + ], + "next_page": 2 + } + } :param query_set 数据库查询结果 :param object_serializer: 序列化单个object的serializer :return response diff --git a/utils/tests.py b/utils/tests.py index 9ab31f9..519870c 100644 --- a/utils/tests.py +++ b/utils/tests.py @@ -35,19 +35,19 @@ class PaginatorTest(APITestCase): response = self.client.get(self.url + "?paging=true") self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) - response = self.client.get(self.url + "?paging=true&limit=-1") + response = self.client.get(self.url + "?paging=true&page_size=-1") self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) - response = self.client.get(self.url + "?paging=true&limit=aa") + response = self.client.get(self.url + "?paging=true&page_size=aa") self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) - response = self.client.get(self.url + "?paging=true&limit=1&page_size=1&page=-1") + response = self.client.get(self.url + "?paging=true&page_size=1&page=-1") self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) - response = self.client.get(self.url + "?paging=true&limit=1&page_size=aaa&page=1") + response = self.client.get(self.url + "?paging=true&page_size=aaa&page=1") self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) - response = self.client.get(self.url + "?paging=true&limit=1&page_size=1&page=aaa") + response = self.client.get(self.url + "?paging=true&page_size=1&page=aaa") self.assertEqual(response.data, {"code": 1, "data": u"参数错误"}) def test_correct_paginate(self): From c5446361db23f10e62257d2128baec6ec0966494 Mon Sep 17 00:00:00 2001 From: virusdefender <1670873886@qq.com> Date: Wed, 5 Aug 2015 19:45:35 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=20admin=20spa?= =?UTF-8?q?=20=E7=9A=84=E9=80=9A=E7=94=A8=E4=BB=A3=E7=A0=81[CI=20SKIP]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oj/urls.py | 4 +- static/src/js/app/admin/admin.js | 31 ++++++++ static/src/js/config.js | 1 + template/admin/admin.html | 122 +++++++++++++++++++++++++++++++ template/admin/index.html | 4 - template/admin/index/index.html | 1 + template/admin_base.html | 8 +- 7 files changed, 162 insertions(+), 9 deletions(-) create mode 100644 static/src/js/app/admin/admin.js create mode 100644 template/admin/admin.html delete mode 100644 template/admin/index.html create mode 100644 template/admin/index/index.html diff --git a/oj/urls.py b/oj/urls.py index 0c8ea51..cc49f42 100644 --- a/oj/urls.py +++ b/oj/urls.py @@ -5,11 +5,12 @@ from django.views.generic import TemplateView from account.views import UserLoginAPIView, UsernameCheckAPIView, UserRegisterAPIView, UserChangePasswordAPIView from announcement.views import AnnouncementAPIView +from admin.views import AdminTemplateView urlpatterns = [ url("^$", TemplateView.as_view(template_name="oj/index.html"), name="index_page"), url(r'^docs/', include('rest_framework_swagger.urls')), - url(r'^admin/$', TemplateView.as_view(template_name="admin/index.html"), name="admin_index_page"), + url(r'^admin/$', TemplateView.as_view(template_name="admin/admin.html"), name="admin_spa_page"), url(r'^login/$', TemplateView.as_view(template_name="oj/account/login.html"), name="user_login_page"), url(r'^register/$', TemplateView.as_view(template_name="oj/account/register.html"), name="user_register_page"), url(r'^change_password/$', TemplateView.as_view(template_name="oj/account/change_password.html"), name="user_change_password_page"), @@ -22,4 +23,5 @@ urlpatterns = [ url(r'^admin/contest/$', TemplateView.as_view(template_name="admin/contest/add_contest.html"), name="add_contest_page"), url(r'^problems/$', TemplateView.as_view(template_name="oj/problem/problem_list.html"), name="problem_list_page"), + url(r'^admin/template/(?P\w+)/(?P\w+).html', AdminTemplateView.as_view(), name="admin_template") ] diff --git a/static/src/js/app/admin/admin.js b/static/src/js/app/admin/admin.js new file mode 100644 index 0000000..d3e30ac --- /dev/null +++ b/static/src/js/app/admin/admin.js @@ -0,0 +1,31 @@ +define("admin", ["jquery", "avalon"], function($, avalon){ + function li_active(selector){ + $(selector).attr("class", "list-group-item active"); + } + + function li_inactive(selector){ + $(".list-group-item").attr("class", "list-group-item"); + } + + var hash = window.location.hash.substring(1); + + if(hash){ + li_active("#li-" + hash); + }else { + li_active("#li-index"); + } + + window.onhashchange = function() { + var hash = window.location.hash.substring(1); + if(hash){ + li_inactive(".list-group-item"); + li_active("#li-" + hash); + vm.template_url = "template/index/" + hash + ".html"; + } + }; + + var vm = avalon.define({ + $id: "admin", + template_url: "template/index/index.html" + }); +}); \ No newline at end of file diff --git a/static/src/js/config.js b/static/src/js/config.js index 3907d1c..079e45c 100644 --- a/static/src/js/config.js +++ b/static/src/js/config.js @@ -15,6 +15,7 @@ var require = { submit_code: "app/oj/problem/submit_code", contest: "app/admin/contest/contest", csrf: "utils/csrf", + admin: "app/admin/admin", //formValidation 不要在代码中单独使用,而是使用和修改utils/validation base: "lib/formValidation/base", diff --git a/template/admin/admin.html b/template/admin/admin.html new file mode 100644 index 0000000..c712084 --- /dev/null +++ b/template/admin/admin.html @@ -0,0 +1,122 @@ + + + + + + + + + + + 在线评测系统 - 后台管理 + + + {% block css_block %}{% endblock %} + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + + +
+ +
+
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/template/admin/index.html b/template/admin/index.html deleted file mode 100644 index df51a66..0000000 --- a/template/admin/index.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "admin_base.html" %} -{% block body %} -Hello world -{% endblock %} \ No newline at end of file diff --git a/template/admin/index/index.html b/template/admin/index/index.html new file mode 100644 index 0000000..6116828 --- /dev/null +++ b/template/admin/index/index.html @@ -0,0 +1 @@ +

Hello world

\ No newline at end of file diff --git a/template/admin_base.html b/template/admin_base.html index 8525b2e..86cf7e2 100644 --- a/template/admin_base.html +++ b/template/admin_base.html @@ -65,14 +65,14 @@ -
+
  • List header
  • -
  • Home
  • -
  • Library
  • +
  • 主页
  • +
  • 公告
  • Applications
  • Another list header
  • Help
  • @@ -108,7 +108,7 @@ {% block js_block %}{% endblock %}