大幅优化数据库查询, 升级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:
# 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)

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

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

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)
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)
# 判题结果的详细信息

View File

@ -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

View File

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

View File

@ -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 = ""