大幅优化数据库查询, 升级django至1.11 LTS, 升级python至3.6.2

This commit is contained in:
zema1 2017-08-29 19:26:38 +08:00
parent 539b45148b
commit 1e4ede6d1a
13 changed files with 57 additions and 33 deletions

View File

@ -1 +1 @@
3.5.0 3.6.2

View File

@ -76,7 +76,7 @@ def check_contest_permission(func):
try: try:
# use self.contest to avoid query contest again in view. # 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: except Contest.DoesNotExist:
return self.error("Contest %s doesn't exist" % contest_id) return self.error("Contest %s doesn't exist" % contest_id)

View File

@ -1,14 +1,16 @@
import time import time
import pytz import pytz
from django.contrib import auth from django.contrib import auth
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.db import connection
from django.utils.deprecation import MiddlewareMixin
from utils.api import JSONResponse from utils.api import JSONResponse
class SessionSecurityMiddleware(object): class SessionSecurityMiddleware(MiddlewareMixin):
def process_request(self, request): def process_request(self, request):
if request.user.is_authenticated() and request.user.is_admin_role(): if request.user.is_authenticated() and request.user.is_admin_role():
if "last_activity" in request.session: if "last_activity" in request.session:
@ -20,7 +22,7 @@ class SessionSecurityMiddleware(object):
request.session["last_activity"] = time.time() request.session["last_activity"] = time.time()
class AdminRoleRequiredMiddleware(object): class AdminRoleRequiredMiddleware(MiddlewareMixin):
def process_request(self, request): def process_request(self, request):
path = request.path_info path = request.path_info
if path.startswith("/admin/") or path.startswith("/api/admin/"): if path.startswith("/admin/") or path.startswith("/api/admin/"):
@ -28,7 +30,19 @@ class AdminRoleRequiredMiddleware(object):
return JSONResponse.response({"error": "login-required", "data": _("Please login in first")}) return JSONResponse.response({"error": "login-required", "data": _("Please login in first")})
class TimezoneMiddleware(object): class TimezoneMiddleware(MiddlewareMixin):
def process_request(self, request): def process_request(self, request):
if request.user.is_authenticated(): if request.user.is_authenticated():
timezone.activate(pytz.timezone(request.user.userprofile.time_zone)) 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

View File

@ -47,7 +47,7 @@ class UserProfileAPI(APIView):
user = request.user user = request.user
except User.DoesNotExist: except User.DoesNotExist:
return self.error("User does not exist") 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) return self.success(UserProfileSerializer(profile).data)
@validate_serializer(EditUserProfileSerializer) @validate_serializer(EditUserProfileSerializer)

View File

@ -18,7 +18,7 @@ class ContestAnnouncementListAPI(APIView):
contest_id = request.GET.get("contest_id") contest_id = request.GET.get("contest_id")
if not contest_id: if not contest_id:
return self.error("Invalid parameter") 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") max_id = request.GET.get("max_id")
if max_id: if max_id:
data = data.filter(id__gt=max_id) data = data.filter(id__gt=max_id)
@ -30,12 +30,12 @@ class ContestAPI(APIView):
contest_id = request.GET.get("id") contest_id = request.GET.get("id")
if contest_id: if contest_id:
try: 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: except Contest.DoesNotExist:
return self.error("Contest doesn't exist.") return self.error("Contest doesn't exist.")
return self.success(ContestSerializer(contest).data) 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") keyword = request.GET.get("keyword")
rule_type = request.GET.get("rule_type") rule_type = request.GET.get("rule_type")
status = request.GET.get("status") status = request.GET.get("status")
@ -101,9 +101,9 @@ class ContestRankAPI(APIView):
@check_contest_permission @check_contest_permission
def get(self, request): def get(self, request):
if self.contest.rule_type == ContestRuleType.ACM: if self.contest.rule_type == ContestRuleType.ACM:
model, serializer = ACMContestRank, ACMContestRankSerializer serializer = ACMContestRankSerializer
else: else:
model, serializer = OIContestRank, OIContestRankSerializer serializer = OIContestRankSerializer
cache_key = CacheKey.contest_rank_cache + str(self.contest.id) cache_key = CacheKey.contest_rank_cache + str(self.contest.id)
qs = default_cache.get(cache_key) qs = default_cache.get(cache_key)

View File

@ -1,4 +1,4 @@
django==1.9.6 django==1.11.4
djangorestframework==3.4.0 djangorestframework==3.4.0
pillow pillow
jsonfield jsonfield

View File

@ -61,7 +61,6 @@ MIDDLEWARE_CLASSES = (
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'account.middleware.AdminRoleRequiredMiddleware', 'account.middleware.AdminRoleRequiredMiddleware',
'account.middleware.SessionSecurityMiddleware', 'account.middleware.SessionSecurityMiddleware',
# 'account.middleware.TimezoneMiddleware'
) )
ROOT_URLCONF = 'oj.urls' ROOT_URLCONF = 'oj.urls'

View File

@ -17,12 +17,12 @@ class ProblemAPI(APIView):
problem_id = request.GET.get("problem_id") problem_id = request.GET.get("problem_id")
if problem_id: if problem_id:
try: 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) return self.success(ProblemSerializer(problem).data)
except Problem.DoesNotExist: except Problem.DoesNotExist:
return self.error("Problem does not exist") 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") tag_text = request.GET.get("tag")
if tag_text: if tag_text:
@ -51,10 +51,10 @@ class ContestProblemAPI(APIView):
problem_id = request.GET.get("problem_id") problem_id = request.GET.get("problem_id")
if problem_id: if problem_id:
try: 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: except ContestProblem.DoesNotExist:
return self.error("Problem does not exist.") return self.error("Problem does not exist.")
return self.success(ContestProblemSerializer(problem).data) 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) return self.success(ContestProblemSerializer(contest_problems, many=True).data)

View File

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

View File

@ -25,6 +25,7 @@ class Submission(models.Model):
problem_id = models.IntegerField(db_index=True) problem_id = models.IntegerField(db_index=True)
create_time = models.DateTimeField(auto_now_add=True) create_time = models.DateTimeField(auto_now_add=True)
user_id = models.IntegerField(db_index=True) user_id = models.IntegerField(db_index=True)
username = models.CharField(max_length=30)
code = models.TextField() code = models.TextField()
result = models.IntegerField(default=JudgeStatus.PENDING) result = models.IntegerField(default=JudgeStatus.PENDING)
# 判题结果的详细信息 # 判题结果的详细信息

View File

@ -1,5 +1,4 @@
from .models import Submission from .models import Submission
from account.models import User
from utils.api import serializers from utils.api import serializers
from judge.languages import language_names from judge.languages import language_names
@ -21,20 +20,14 @@ class SubmissionModelSerializer(serializers.ModelSerializer):
# 不显示submission info详情的serializer # 不显示submission info详情的serializer
class SubmissionSafeSerializer(serializers.ModelSerializer): class SubmissionSafeSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField()
statistic_info = serializers.JSONField() statistic_info = serializers.JSONField()
class Meta: class Meta:
model = Submission model = Submission
exclude = ("info", "contest_id") exclude = ("info", "contest_id")
@staticmethod
def get_username(obj):
return User.objects.get(id=obj.user_id).username
class SubmissionListSerializer(serializers.ModelSerializer): class SubmissionListSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField()
statistic_info = serializers.JSONField() statistic_info = serializers.JSONField()
show_link = serializers.SerializerMethodField() show_link = serializers.SerializerMethodField()
@ -47,10 +40,7 @@ class SubmissionListSerializer(serializers.ModelSerializer):
exclude = ("info", "contest_id", "code") exclude = ("info", "contest_id", "code")
def get_show_link(self, obj): 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 False
return obj.check_user_permission(self.user) return obj.check_user_permission(self.user)
@staticmethod
def get_username(obj):
return User.objects.get(id=obj.user_id).username

View File

@ -34,6 +34,7 @@ def _submit(response, user, problem_id, language, code, contest_id):
return response.error("Problem not exist") return response.error("Problem not exist")
submission = Submission.objects.create(user_id=user.id, submission = Submission.objects.create(user_id=user.id,
username=user.username,
language=language, language=language,
code=code, code=code,
problem_id=problem._id, problem_id=problem._id,

View File

@ -4,8 +4,6 @@ from utils.xss_filter import XssHtml
class RichTextField(models.TextField): class RichTextField(models.TextField):
__metaclass__ = models.SubfieldBase
def get_prep_value(self, value): def get_prep_value(self, value):
if not value: if not value:
value = "" value = ""