mirror of
https://github.com/DMOJ/online-judge.git
synced 2024-11-25 16:32:37 +08:00
Rework misc config to run exactly one query
There should never be that much stuff in MiscConfig, so let's just read it all and deal with it in python instead of trying to run one query for each item of interest and poorly cache it. This PR also moved MiscConfigDict into a middleware so it can be used outside of templates.
This commit is contained in:
parent
6ecec69904
commit
eda67c54e2
@ -287,6 +287,7 @@ MIDDLEWARE = (
|
||||
'judge.middleware.APIMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'judge.middleware.MiscConfigMiddleware',
|
||||
'judge.middleware.DMOJLoginMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
|
@ -6,11 +6,15 @@ from urllib.parse import quote
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.urls import Resolver404, resolve, reverse
|
||||
from django.utils.encoding import force_bytes
|
||||
from requests.exceptions import HTTPError
|
||||
|
||||
from judge.models import MiscConfig
|
||||
|
||||
try:
|
||||
import uwsgi
|
||||
except ImportError:
|
||||
@ -130,3 +134,46 @@ class APIMiddleware(object):
|
||||
response.status_code = 401
|
||||
return response
|
||||
return self.get_response(request)
|
||||
|
||||
|
||||
class MiscConfigDict(dict):
|
||||
__slots__ = ('language', 'site', 'backing')
|
||||
|
||||
def __init__(self, language='', domain=None):
|
||||
self.language = language
|
||||
self.site = domain
|
||||
self.backing = None
|
||||
super().__init__()
|
||||
|
||||
def __missing__(self, key):
|
||||
if self.backing is None:
|
||||
cache_key = 'misc_config'
|
||||
backing = cache.get(cache_key)
|
||||
if backing is None:
|
||||
backing = dict(MiscConfig.objects.values_list('key', 'value'))
|
||||
cache.set(cache_key, backing, 86400)
|
||||
self.backing = backing
|
||||
|
||||
keys = ['%s.%s' % (key, self.language), key] if self.language else [key]
|
||||
if self.site is not None:
|
||||
keys = ['%s:%s' % (self.site, key) for key in keys] + keys
|
||||
|
||||
for attempt in keys:
|
||||
result = self.backing.get(attempt)
|
||||
if result is not None:
|
||||
break
|
||||
else:
|
||||
result = ''
|
||||
|
||||
self[key] = result
|
||||
return result
|
||||
|
||||
|
||||
class MiscConfigMiddleware:
|
||||
def __init__(self, get_response):
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
domain = get_current_site(request).domain
|
||||
request.misc_config = MiscConfigDict(language=request.LANGUAGE_CODE, domain=domain)
|
||||
return self.get_response(request)
|
||||
|
@ -2,10 +2,9 @@ import errno
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.cache import cache
|
||||
from django.core.cache.utils import make_template_fragment_key
|
||||
from django.db.models.signals import post_delete, post_save, pre_save
|
||||
from django.db.models.signals import post_delete, post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from .caching import finished_submission
|
||||
@ -128,35 +127,14 @@ def organization_update(sender, instance, **kwargs):
|
||||
for engine in EFFECTIVE_MATH_ENGINES])
|
||||
|
||||
|
||||
_misc_config_i18n = [code for code, _ in settings.LANGUAGES]
|
||||
_misc_config_i18n.append('')
|
||||
|
||||
|
||||
def misc_config_cache_delete(key):
|
||||
cache.delete_many(['misc_config:%s:%s:%s' % (domain, lang, key.split('.')[0])
|
||||
for lang in _misc_config_i18n
|
||||
for domain in Site.objects.values_list('domain', flat=True)])
|
||||
|
||||
|
||||
@receiver(pre_save, sender=MiscConfig)
|
||||
def misc_config_pre_save(sender, instance, **kwargs):
|
||||
try:
|
||||
old_key = MiscConfig.objects.filter(id=instance.id).values_list('key').get()[0]
|
||||
except MiscConfig.DoesNotExist:
|
||||
old_key = None
|
||||
instance._old_key = old_key
|
||||
|
||||
|
||||
@receiver(post_save, sender=MiscConfig)
|
||||
def misc_config_update(sender, instance, **kwargs):
|
||||
misc_config_cache_delete(instance.key)
|
||||
if instance._old_key is not None and instance._old_key != instance.key:
|
||||
misc_config_cache_delete(instance._old_key)
|
||||
cache.delete('misc_config')
|
||||
|
||||
|
||||
@receiver(post_delete, sender=MiscConfig)
|
||||
def misc_config_delete(sender, instance, **kwargs):
|
||||
misc_config_cache_delete(instance.key)
|
||||
cache.delete('misc_config')
|
||||
|
||||
|
||||
@receiver(post_save, sender=ContestSubmission)
|
||||
|
@ -3,11 +3,10 @@ from functools import partial
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.context_processors import PermWrapper
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.cache import cache
|
||||
from django.utils.functional import SimpleLazyObject, new_method_proxy
|
||||
|
||||
from judge.utils.caniuse import CanIUse, SUPPORT
|
||||
from .models import MiscConfig, NavigationBar, Profile
|
||||
from .models import NavigationBar, Profile
|
||||
|
||||
|
||||
class FixedSimpleLazyObject(SimpleLazyObject):
|
||||
@ -71,37 +70,8 @@ def site(request):
|
||||
return {'site': get_current_site(request)}
|
||||
|
||||
|
||||
class MiscConfigDict(dict):
|
||||
__slots__ = ('language', 'site')
|
||||
|
||||
def __init__(self, language='', domain=None):
|
||||
self.language = language
|
||||
self.site = domain
|
||||
super(MiscConfigDict, self).__init__()
|
||||
|
||||
def __missing__(self, key):
|
||||
cache_key = 'misc_config:%s:%s:%s' % (self.site, self.language, key)
|
||||
value = cache.get(cache_key)
|
||||
if value is None:
|
||||
keys = ['%s.%s' % (key, self.language), key] if self.language else [key]
|
||||
if self.site is not None:
|
||||
keys = ['%s:%s' % (self.site, key) for key in keys] + keys
|
||||
map = dict(MiscConfig.objects.values_list('key', 'value').filter(key__in=keys))
|
||||
for item in keys:
|
||||
if item in map:
|
||||
value = map[item]
|
||||
break
|
||||
else:
|
||||
value = ''
|
||||
cache.set(cache_key, value, 86400)
|
||||
self[key] = value
|
||||
return value
|
||||
|
||||
|
||||
def misc_config(request):
|
||||
domain = get_current_site(request).domain
|
||||
return {'misc_config': MiscConfigDict(domain=domain),
|
||||
'i18n_config': MiscConfigDict(language=request.LANGUAGE_CODE, domain=domain)}
|
||||
return {'misc_config': request.misc_config}
|
||||
|
||||
|
||||
def site_name(request):
|
||||
|
@ -281,8 +281,8 @@
|
||||
<div id="content-body">{% block body %}{% endblock %}</div>
|
||||
</main>
|
||||
|
||||
{% if i18n_config.announcement %}
|
||||
<div id="announcement">{{ i18n_config.announcement|safe }}</div>
|
||||
{% if misc_config.announcement %}
|
||||
<div id="announcement">{{ misc_config.announcement|safe }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% block bodyend %}{% endblock %}
|
||||
@ -291,8 +291,8 @@
|
||||
<span id="footer-content">
|
||||
<br>
|
||||
<a style="color: #808080" href="https://dmoj.ca">{{ _('proudly powered by **DMOJ**')|markdown('default', strip_paragraphs=True) }}</a> |
|
||||
{% if i18n_config.footer %}
|
||||
{{ i18n_config.footer|safe }} |
|
||||
{% if misc_config.footer %}
|
||||
{{ misc_config.footer|safe }} |
|
||||
{% endif %}
|
||||
<form action="{{ url('set_language') }}" method="post" style="display: inline">
|
||||
{% csrf_token %}
|
||||
|
@ -1,12 +1,12 @@
|
||||
{% extends "blog/list.html" %}
|
||||
{% block before_posts %}
|
||||
{% if i18n_config.home_page_top %}
|
||||
{{ render_django(i18n_config.home_page_top, request=request, user_count=user_count, problem_count=problem_count, submission_count=submission_count, language_count=language_count, perms=perms) }}
|
||||
{% if misc_config.home_page_top %}
|
||||
{{ render_django(misc_config.home_page_top, request=request, user_count=user_count, problem_count=problem_count, submission_count=submission_count, language_count=language_count, perms=perms) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block meta %}
|
||||
{% if i18n_config.meta_description %}
|
||||
<meta name="description" content="{{ i18n_config['meta_description'] }}">
|
||||
{% if misc_config.meta_description %}
|
||||
<meta name="description" content="{{ misc_config['meta_description'] }}">
|
||||
{% endif %}
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user