From 50b64f6cf55e898cf92251ad0f9f7e802f50959a Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 16 Jun 2023 10:35:05 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20category=20?= =?UTF-8?q?=E5=BC=95=E8=B5=B7=E7=9A=84=20sql=20=E6=9F=A5=E8=AF=A2=E8=BF=87?= =?UTF-8?q?=E5=A4=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pref: stash perf: 添加装饰器 perf: 优化 category api --- apps/assets/const/custom.py | 29 +++++++++++++++++++++-------- apps/assets/const/types.py | 1 - apps/authentication/views/login.py | 17 +++++++++-------- apps/common/decorators.py | 22 ++++++++++++++++++++++ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/apps/assets/const/custom.py b/apps/assets/const/custom.py index 5c72127b3..878207f26 100644 --- a/apps/assets/const/custom.py +++ b/apps/assets/const/custom.py @@ -1,3 +1,6 @@ +from collections import defaultdict + +from common.decorators import cached_method from .base import BaseType @@ -9,7 +12,8 @@ class CustomTypes(BaseType): except Exception: return [] types = set([p.type for p in platforms]) - return [(t, t) for t in types] + choices = [(t, t) for t in types] + return choices @classmethod def _get_base_constrains(cls) -> dict: @@ -37,13 +41,20 @@ class CustomTypes(BaseType): return constrains @classmethod + @cached_method(5) def _get_protocol_constrains(cls) -> dict: - constrains = {} - for platform in cls.get_custom_platforms(): - choices = list(platform.protocols.values_list('name', flat=True)) - if platform.type in constrains: - choices = constrains[platform.type]['choices'] + choices - constrains[platform.type] = {'choices': choices} + from assets.models import PlatformProtocol + _constrains = defaultdict(set) + protocols = PlatformProtocol.objects \ + .filter(platform__category='custom') \ + .values_list('name', 'platform__type') + for name, tp in protocols: + _constrains[tp].add(name) + + constrains = { + tp: {'choices': list(choices)} + for tp, choices in _constrains.items() + } return constrains @classmethod @@ -51,6 +62,8 @@ class CustomTypes(BaseType): return {} @classmethod + @cached_method(5) def get_custom_platforms(cls): from assets.models import Platform - return Platform.objects.filter(category='custom') + platforms = Platform.objects.filter(category='custom') + return platforms diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 69fa36bb3..1f0156b7f 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -193,7 +193,6 @@ class AllTypes(ChoicesMixin): } return node - @classmethod def asset_to_node(cls, asset, pid): node = { diff --git a/apps/authentication/views/login.py b/apps/authentication/views/login.py index dfba7155c..acc8ed51c 100644 --- a/apps/authentication/views/login.py +++ b/apps/authentication/views/login.py @@ -2,15 +2,19 @@ # from __future__ import unicode_literals -import os + import datetime +import os from typing import Callable -from django.db import IntegrityError -from django.templatetags.static import static +from django.conf import settings +from django.contrib.auth import BACKEND_SESSION_KEY from django.contrib.auth import login as auth_login, logout as auth_logout -from django.http import HttpResponse, HttpRequest +from django.db import IntegrityError +from django.http import HttpRequest, HttpResponse from django.shortcuts import reverse, redirect +from django.templatetags.static import static +from django.urls import reverse_lazy from django.utils.decorators import method_decorator from django.utils.translation import ugettext as _, get_language from django.views.decorators.cache import never_cache @@ -18,16 +22,13 @@ from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_post_parameters from django.views.generic.base import TemplateView, RedirectView from django.views.generic.edit import FormView -from django.conf import settings -from django.urls import reverse_lazy -from django.contrib.auth import BACKEND_SESSION_KEY from common.utils import FlashMessageUtil, static_or_direct from users.utils import ( redirect_user_first_login_or_index ) -from ..const import RSA_PRIVATE_KEY, RSA_PUBLIC_KEY from .. import mixins, errors +from ..const import RSA_PRIVATE_KEY, RSA_PUBLIC_KEY from ..forms import get_user_login_form_cls __all__ = [ diff --git a/apps/common/decorators.py b/apps/common/decorators.py index c100c5025..4881c1517 100644 --- a/apps/common/decorators.py +++ b/apps/common/decorators.py @@ -6,6 +6,7 @@ import inspect import threading import time from concurrent.futures import ThreadPoolExecutor +from functools import wraps from django.db import transaction @@ -217,3 +218,24 @@ def do_test(): end = time.time() using = end - s print("end : %s, using: %s" % (end, using)) + + +def cached_method(ttl=20): + _cache = {} + + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + key = (func, args, tuple(sorted(kwargs.items()))) + # 检查缓存是否存在且未过期 + if key in _cache and time.time() - _cache[key]['timestamp'] < ttl: + return _cache[key]['result'] + + # 缓存过期或不存在,执行方法并缓存结果 + result = func(*args, **kwargs) + _cache[key] = {'result': result, 'timestamp': time.time()} + return result + + return wrapper + + return decorator