diff --git a/.python-version b/.python-version index 1545d966..b7276283 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.5.0 +3.6.2 diff --git a/account/decorators.py b/account/decorators.py index 1697a50d..0b14f89f 100644 --- a/account/decorators.py +++ b/account/decorators.py @@ -76,7 +76,7 @@ def check_contest_permission(func): try: # use self.contest to avoid query contest again in view. - self.contest = Contest.objects.get(id=contest_id, visible=True) + self.contest = Contest.objects.select_related("created_by").get(id=contest_id, visible=True) except Contest.DoesNotExist: return self.error("Contest %s doesn't exist" % contest_id) diff --git a/account/middleware.py b/account/middleware.py index f510fd2e..dac102dd 100644 --- a/account/middleware.py +++ b/account/middleware.py @@ -1,14 +1,16 @@ import time - import pytz + from django.contrib import auth from django.utils import timezone from django.utils.translation import ugettext as _ +from django.db import connection +from django.utils.deprecation import MiddlewareMixin from utils.api import JSONResponse -class SessionSecurityMiddleware(object): +class SessionSecurityMiddleware(MiddlewareMixin): def process_request(self, request): if request.user.is_authenticated() and request.user.is_admin_role(): if "last_activity" in request.session: @@ -20,15 +22,27 @@ class SessionSecurityMiddleware(object): request.session["last_activity"] = time.time() -class AdminRoleRequiredMiddleware(object): +class AdminRoleRequiredMiddleware(MiddlewareMixin): def process_request(self, request): path = request.path_info if path.startswith("/admin/") or path.startswith("/api/admin/"): - if not(request.user.is_authenticated() and request.user.is_admin_role()): + if not (request.user.is_authenticated() and request.user.is_admin_role()): return JSONResponse.response({"error": "login-required", "data": _("Please login in first")}) -class TimezoneMiddleware(object): +class TimezoneMiddleware(MiddlewareMixin): def process_request(self, request): if request.user.is_authenticated(): timezone.activate(pytz.timezone(request.user.userprofile.time_zone)) + + +class LogSqlMiddleware(MiddlewareMixin): + def process_response(self, request, response): + print("\033[94m", "#" * 30, "\033[0m") + time_threshold = 0.03 + for query in connection.queries: + if float(query["time"]) > time_threshold: + print("\033[93m", query, "\n", "-" * 30, "\033[0m") + else: + print(query, "\n", "-" * 30) + return response diff --git a/account/views/oj.py b/account/views/oj.py index b1f57983..dda41c77 100644 --- a/account/views/oj.py +++ b/account/views/oj.py @@ -47,7 +47,7 @@ class UserProfileAPI(APIView): user = request.user except User.DoesNotExist: return self.error("User does not exist") - profile = UserProfile.objects.get(user=user) + profile = UserProfile.objects.select_related("user").get(user=user) return self.success(UserProfileSerializer(profile).data) @validate_serializer(EditUserProfileSerializer) diff --git a/contest/views/oj.py b/contest/views/oj.py index 28ee1bc2..b25019c5 100644 --- a/contest/views/oj.py +++ b/contest/views/oj.py @@ -18,7 +18,7 @@ class ContestAnnouncementListAPI(APIView): contest_id = request.GET.get("contest_id") if not contest_id: return self.error("Invalid parameter") - data = ContestAnnouncement.objects.filter(contest_id=contest_id) + data = ContestAnnouncement.objects.select_related("created_by").filter(contest_id=contest_id) max_id = request.GET.get("max_id") if max_id: data = data.filter(id__gt=max_id) @@ -30,12 +30,12 @@ class ContestAPI(APIView): contest_id = request.GET.get("id") if contest_id: try: - contest = Contest.objects.get(id=contest_id, visible=True) + contest = Contest.objects.select_related("created_by").get(id=contest_id, visible=True) except Contest.DoesNotExist: return self.error("Contest doesn't exist.") return self.success(ContestSerializer(contest).data) - contests = Contest.objects.filter(visible=True) + contests = Contest.objects.select_related("created_by").filter(visible=True) keyword = request.GET.get("keyword") rule_type = request.GET.get("rule_type") status = request.GET.get("status") @@ -101,9 +101,9 @@ class ContestRankAPI(APIView): @check_contest_permission def get(self, request): if self.contest.rule_type == ContestRuleType.ACM: - model, serializer = ACMContestRank, ACMContestRankSerializer + serializer = ACMContestRankSerializer else: - model, serializer = OIContestRank, OIContestRankSerializer + serializer = OIContestRankSerializer cache_key = CacheKey.contest_rank_cache + str(self.contest.id) qs = default_cache.get(cache_key) diff --git a/deploy/requirements.txt b/deploy/requirements.txt index b843e277..1d2032c9 100644 --- a/deploy/requirements.txt +++ b/deploy/requirements.txt @@ -1,4 +1,4 @@ -django==1.9.6 +django==1.11.4 djangorestframework==3.4.0 pillow jsonfield diff --git a/oj/settings.py b/oj/settings.py index a8e02676..ed06ec9d 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -61,7 +61,6 @@ MIDDLEWARE_CLASSES = ( 'django.middleware.security.SecurityMiddleware', 'account.middleware.AdminRoleRequiredMiddleware', 'account.middleware.SessionSecurityMiddleware', - # 'account.middleware.TimezoneMiddleware' ) ROOT_URLCONF = 'oj.urls' diff --git a/problem/views/oj.py b/problem/views/oj.py index edc1c1be..930e0d9c 100644 --- a/problem/views/oj.py +++ b/problem/views/oj.py @@ -17,12 +17,12 @@ class ProblemAPI(APIView): problem_id = request.GET.get("problem_id") if problem_id: try: - problem = Problem.objects.get(_id=problem_id, visible=True) + problem = Problem.objects.select_related("created_by").get(_id=problem_id, visible=True) return self.success(ProblemSerializer(problem).data) except Problem.DoesNotExist: return self.error("Problem does not exist") - problems = Problem.objects.filter(visible=True) + problems = Problem.objects.select_related("created_by").filter(visible=True) # 按照标签筛选 tag_text = request.GET.get("tag") if tag_text: @@ -51,10 +51,10 @@ class ContestProblemAPI(APIView): problem_id = request.GET.get("problem_id") if problem_id: try: - problem = ContestProblem.objects.get(_id=problem_id, contest=self.contest, visible=True) + problem = ContestProblem.objects.select_related("created_by").get(_id=problem_id, contest=self.contest, visible=True) except ContestProblem.DoesNotExist: return self.error("Problem does not exist.") return self.success(ContestProblemSerializer(problem).data) - contest_problems = ContestProblem.objects.filter(contest=self.contest, visible=True) + contest_problems = ContestProblem.objects.select_related("created_by").filter(contest=self.contest, visible=True) return self.success(ContestProblemSerializer(contest_problems, many=True).data) diff --git a/submission/migrations/0005_submission_username.py b/submission/migrations/0005_submission_username.py new file mode 100644 index 00000000..46f63dfd --- /dev/null +++ b/submission/migrations/0005_submission_username.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.4 on 2017-08-26 03:47 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submission', '0004_auto_20170717_1324'), + ] + + operations = [ + migrations.AddField( + model_name='submission', + name='username', + field=models.CharField(default="", max_length=30), + preserve_default=False, + ), + ] diff --git a/submission/models.py b/submission/models.py index 65d242b6..45130beb 100644 --- a/submission/models.py +++ b/submission/models.py @@ -25,6 +25,7 @@ class Submission(models.Model): problem_id = models.IntegerField(db_index=True) create_time = models.DateTimeField(auto_now_add=True) user_id = models.IntegerField(db_index=True) + username = models.CharField(max_length=30) code = models.TextField() result = models.IntegerField(default=JudgeStatus.PENDING) # 判题结果的详细信息 diff --git a/submission/serializers.py b/submission/serializers.py index 815d2757..d2fe4ada 100644 --- a/submission/serializers.py +++ b/submission/serializers.py @@ -1,5 +1,4 @@ from .models import Submission -from account.models import User from utils.api import serializers from judge.languages import language_names @@ -21,20 +20,14 @@ class SubmissionModelSerializer(serializers.ModelSerializer): # 不显示submission info详情的serializer class SubmissionSafeSerializer(serializers.ModelSerializer): - username = serializers.SerializerMethodField() statistic_info = serializers.JSONField() class Meta: model = Submission exclude = ("info", "contest_id") - @staticmethod - def get_username(obj): - return User.objects.get(id=obj.user_id).username - class SubmissionListSerializer(serializers.ModelSerializer): - username = serializers.SerializerMethodField() statistic_info = serializers.JSONField() show_link = serializers.SerializerMethodField() @@ -47,10 +40,7 @@ class SubmissionListSerializer(serializers.ModelSerializer): exclude = ("info", "contest_id", "code") def get_show_link(self, obj): - if self.user.id is None: + # 没传user或为匿名user + if self.user is None or self.user.id is None: return False return obj.check_user_permission(self.user) - - @staticmethod - def get_username(obj): - return User.objects.get(id=obj.user_id).username diff --git a/submission/views/oj.py b/submission/views/oj.py index 88892018..27abc10e 100644 --- a/submission/views/oj.py +++ b/submission/views/oj.py @@ -34,6 +34,7 @@ def _submit(response, user, problem_id, language, code, contest_id): return response.error("Problem not exist") submission = Submission.objects.create(user_id=user.id, + username=user.username, language=language, code=code, problem_id=problem._id, diff --git a/utils/models.py b/utils/models.py index a3e15b06..b651aa2d 100644 --- a/utils/models.py +++ b/utils/models.py @@ -4,8 +4,6 @@ from utils.xss_filter import XssHtml class RichTextField(models.TextField): - __metaclass__ = models.SubfieldBase - def get_prep_value(self, value): if not value: value = ""