Skip to content

Commit 0ecbb75

Browse files
committed
Merge branch 'dev'
# Conflicts: # Dockerfile
2 parents 7ddaa81 + 9ae57b5 commit 0ecbb75

File tree

22 files changed

+154
-96
lines changed

22 files changed

+154
-96
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM nineaiyu/xadmin-server-base:20241129_024544 AS stage-build
1+
FROM nineaiyu/xadmin-server-base:20241129_074632 AS stage-build
22
ARG VERSION
33

44
WORKDIR /data/xadmin-server

common/base/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ def format_menu_meta(meta: dict) -> dict:
146146
def format_menu_data(data):
147147
new_result = []
148148
for d in data:
149-
if d.get('count', -1) < 2:
149+
if d.get('count', -1) < 1:
150150
route = {
151151
'path': f"/default{d.get('path')}",
152152
'title': d.get('title'),

common/core/fields.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from rest_framework.serializers import RelatedField, MultipleChoiceField
1818

1919
from common.core.filter import get_filter_queryset
20+
from server.utils import get_current_request
2021

2122

2223
def attr_get(obj, attr, sp='.'):
@@ -81,9 +82,8 @@ class BasePrimaryKeyRelatedField(RelatedField):
8182
"queryset_none": _("The query set is empty."),
8283
}
8384

84-
def __init__(self, request=None, attrs=None, ignore_field_permission=False, **kwargs):
85+
def __init__(self, attrs=None, ignore_field_permission=False, **kwargs):
8586
"""
86-
:param request:
8787
:param attrs: 默认为 None,返回默认的 pk, 一般需要自定义
8888
:param ignore_field_permission: 忽略字段权限控制
8989
"""
@@ -92,16 +92,15 @@ def __init__(self, request=None, attrs=None, ignore_field_permission=False, **kw
9292
self.input_type = kwargs.pop("input_type", '')
9393
self.many = kwargs.get("many", False)
9494
super().__init__(**kwargs)
95-
self.request: Request = request or self.context.get("request", None)
95+
self.request: Request = get_current_request()
9696
self.ignore_field_permission = ignore_field_permission
9797

9898
def use_pk_only_optimization(self):
9999
return False
100100

101101
def __add_request(self):
102-
request = self.context.get("request", None)
103102
if not self.request:
104-
self.request = request
103+
self.request = get_current_request()
105104

106105
def get_queryset(self):
107106
self.__add_request()

common/core/middleware.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from rest_framework.utils import encoders
1515

1616
from common.utils import get_logger
17-
from common.utils.request import get_request_user, get_request_ip, get_request_data, get_request_path, get_os, \
17+
from common.utils.request import get_request_user, get_request_ip, get_request_data, get_os, \
1818
get_browser, get_verbose_name
1919
from system.models import OperationLog
2020

@@ -34,7 +34,6 @@ def __init__(self, get_response=None):
3434
def __handle_request(cls, request):
3535
request.request_ip = get_request_ip(request)
3636
request.request_data = get_request_data(request)
37-
request.request_path = get_request_path(request)
3837
request.request_start_time = time.time()
3938
logger.debug(f"request start. {request.method} {request.path} {getattr(request, 'request_data', {})}")
4039

@@ -80,7 +79,7 @@ def __handle_response(self, request, response):
8079
'dept_belong_id': getattr(request.user, 'dept_id', None),
8180
'ipaddress': getattr(request, 'request_ip'),
8281
'method': request.method,
83-
'path': request.request_path,
82+
'path': request.path,
8483
'body': json.dumps(body) if isinstance(body, dict) else body,
8584
'response_code': response.status_code,
8685
'system': get_os(request),
@@ -105,10 +104,10 @@ def process_view(self, request, view_func, view_args, view_kwargs):
105104
if self.methods == 'ALL' or request.method in self.methods:
106105
model, v = get_verbose_name(view_func.cls.queryset, view_func.cls)
107106
if (model and request.method in self.ignores.get(model._meta.label, [])) or (
108-
request.method in self.ignores.get(request.request_path, [])):
107+
request.method in self.ignores.get(request.path, [])):
109108
return
110109
if not v:
111-
v = settings.API_MODEL_MAP.get(request.request_path, v)
110+
v = settings.API_MODEL_MAP.get(request.path, v)
112111
if not v and model:
113112
v = model._meta.label
114113
log = OperationLog(module=v)

common/core/modelset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
# date : 6/2/2023
77
import itertools
88
import json
9-
import math
109
import uuid
1110
from hashlib import md5
1211
from typing import Callable
1312

13+
import math
1414
from django.conf import settings
1515
from django.db import transaction
1616
from django.forms.widgets import SelectMultiple, DateTimeInput

common/core/permission.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
# author : ly_13
66
# date : 6/6/2023
77
import re
8+
import uuid
89

910
from django.conf import settings
1011
from django.db.models import Q
@@ -13,6 +14,7 @@
1314
from rest_framework.permissions import BasePermission
1415

1516
from common.base.magic import MagicCacheData
17+
from server.utils import get_current_request, set_current_request
1618
from system.models import Menu, FieldPermission
1719

1820

@@ -92,6 +94,9 @@ class IsAuthenticated(BasePermission):
9294
def has_permission(self, request, view):
9395
auth = bool(request.user and request.user.is_authenticated)
9496
if auth:
97+
request.request_uuid = getattr(get_current_request(), "request_uuid", uuid.uuid4())
98+
set_current_request(request)
99+
95100
if request.user.is_superuser:
96101
request.ignore_field_permission = True
97102
return True

common/core/response.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
from django.utils.translation import gettext_lazy as _
99
from rest_framework.response import Response
1010

11-
from server.utils import current_request
11+
from server.utils import get_current_request
1212

1313

1414
class ApiResponse(Response):
1515
def __init__(self, code=1000, detail=None, data=None, status=None, headers=None, content_type=None, **kwargs):
1616
dic = {
1717
'code': code,
1818
'detail': detail if detail else (_("Operation successful") if code == 1000 else _("Operation failed")),
19-
'requestId': str(getattr(current_request, 'request_uuid', ""))
19+
'requestId': str(getattr(get_current_request(), 'request_uuid', ""))
2020
}
2121
if data is not None:
2222
dic['data'] = data

common/core/serializers.py

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from rest_framework.serializers import ModelSerializer
1414

1515
from common.core.fields import BasePrimaryKeyRelatedField, LabeledChoiceField
16+
from server.utils import get_current_request
1617

1718

1819
class BaseModelSerializer(ModelSerializer):
@@ -32,21 +33,6 @@ def get_value(self, dictionary):
3233
# return html.parse_html_dict(dictionary, prefix=self.field_name) or empty
3334
return dictionary.get(self.field_name, empty)
3435

35-
def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs):
36-
"""
37-
# 该方法是为了让继承BaseModelSerializer的方法,增加request传参,例如下面,为meta这个字段的序列化增加request参数
38-
class MenuSerializer(BaseModelSerializer):
39-
meta = MenuMetaSerializer()
40-
"""
41-
for field_name in declared_fields:
42-
if declared_fields[field_name] and isinstance(declared_fields[field_name],
43-
(BaseModelSerializer, BasePrimaryKeyRelatedField)):
44-
obj = declared_fields[field_name]
45-
declared_fields[field_name] = obj.__class__(*obj._args, **obj._kwargs, request=self.request)
46-
47-
extra_kwargs, hidden_fields = super().get_uniqueness_extra_kwargs(field_names, declared_fields, extra_kwargs)
48-
return super().get_uniqueness_extra_kwargs(field_names, declared_fields, extra_kwargs)
49-
5036
def get_allow_fields(self, fields, ignore_field_permission):
5137
"""
5238
self.fields: 默认定义的字段
@@ -74,7 +60,7 @@ def get_allow_fields(self, fields, ignore_field_permission):
7460

7561
return set(fields) & _fields & set(allow_fields)
7662

77-
def __init__(self, instance=None, data=empty, request=None, fields=None, ignore_field_permission=False, **kwargs):
63+
def __init__(self, instance=None, data=empty, fields=None, ignore_field_permission=False, **kwargs):
7864
"""
7965
:param instance:
8066
:param data:
@@ -83,7 +69,7 @@ def __init__(self, instance=None, data=empty, request=None, fields=None, ignore_
8369
:param ignore_field_permission: 忽略字段权限控制
8470
"""
8571
super().__init__(instance, data, **kwargs)
86-
self.request: Request = request or self.context.get("request", None)
72+
self.request: Request = get_current_request()
8773
if self.request is None:
8874
return
8975
allowed = self.get_allow_fields(fields, ignore_field_permission)
@@ -100,20 +86,3 @@ def build_standard_field(self, field_name, model_field):
10086
field_kwargs.setdefault("default", default)
10187
return field_class, field_kwargs
10288

103-
def create(self, validated_data):
104-
if self.request:
105-
user = self.request.user
106-
if user and user.is_authenticated:
107-
if hasattr(self.Meta.model, 'creator') or hasattr(self.instance, 'creator'):
108-
validated_data["creator"] = user
109-
if hasattr(self.Meta.model, 'dept_belong') or hasattr(self.instance, 'dept_belong'):
110-
validated_data["dept_belong"] = user.dept
111-
return super().create(validated_data)
112-
113-
def update(self, instance, validated_data):
114-
if self.request:
115-
user = self.request.user
116-
if user and user.is_authenticated:
117-
if hasattr(self.instance, 'modifier'):
118-
validated_data["modifier"] = user
119-
return super().update(instance, validated_data)

common/local.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66
# date : 10/18/2024
77

88

9-
from werkzeug.local import Local
10-
11-
thread_local = Local()
9+
from asgiref.local import Local
1210

11+
thread_local = Local(thread_critical=True)
1312

1413
def _find(attr):
1514
return getattr(thread_local, attr, None)

common/signal_handlers.py

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@
55
# author : ly_13
66
# date : 6/29/2023
77
import logging
8+
import re
9+
from collections import defaultdict
810

911
from celery import signature
1012
from celery.signals import worker_ready, worker_shutdown, after_setup_logger
13+
from django.conf import settings
1114
from django.core.cache import cache
12-
from django.db.models.signals import pre_delete
15+
from django.core.signals import request_finished
16+
from django.db import connection
17+
from django.db.models.signals import pre_delete, pre_save
1318
from django.dispatch import receiver
1419
from django_celery_beat.models import PeriodicTask
1520
from django_celery_results.models import TaskResult
@@ -19,10 +24,13 @@
1924
from common.celery.logger import CeleryThreadTaskFileHandler
2025
from common.celery.utils import get_celery_task_log_path
2126
from common.utils import get_logger
27+
from server.utils import get_current_request
2228

2329
logger = get_logger(__name__)
2430
safe_str = lambda x: x
2531

32+
pattern = re.compile(r'FROM `(\w+)`')
33+
2634

2735
@worker_ready.connect
2836
def on_app_ready(sender=None, headers=None, **kwargs):
@@ -61,7 +69,6 @@ def delete_file_handler(sender, **kwargs):
6169
log_path = get_celery_task_log_path(task_id)
6270
remove_file(log_path)
6371

64-
6572
@after_setup_logger.connect
6673
def on_after_setup_logger(sender=None, logger=None, loglevel=None, format=None, **kwargs):
6774
if not logger:
@@ -71,3 +78,82 @@ def on_after_setup_logger(sender=None, logger=None, loglevel=None, format=None,
7178
formatter = logging.Formatter(format)
7279
task_handler.setFormatter(formatter)
7380
logger.addHandler(task_handler)
81+
82+
83+
class Counter:
84+
def __init__(self):
85+
self.counter = 0
86+
self.time = 0
87+
88+
def __gt__(self, other):
89+
return self.counter > other.counter
90+
91+
def __lt__(self, other):
92+
return self.counter < other.counter
93+
94+
def __eq__(self, other):
95+
return self.counter == other.counter
96+
97+
98+
def on_request_finished_logging_db_query(sender, **kwargs):
99+
queries = connection.queries
100+
counters = defaultdict(Counter)
101+
table_queries = defaultdict(list)
102+
for query in queries:
103+
if not query['sql'] or not query['sql'].startswith('SELECT'):
104+
continue
105+
tables = pattern.findall(query['sql'])
106+
table_name = ''.join(tables)
107+
time = query['time']
108+
counters[table_name].counter += 1
109+
counters[table_name].time += float(time)
110+
counters['total'].counter += 1
111+
counters['total'].time += float(time)
112+
table_queries[table_name].append(query)
113+
114+
counters = sorted(counters.items(), key=lambda x: x[1])
115+
if not counters:
116+
return
117+
118+
method = 'GET'
119+
path = '/Unknown'
120+
current_request = get_current_request()
121+
if current_request:
122+
method = current_request.method
123+
path = current_request.get_full_path()
124+
125+
print(">>>. [{}] {}".format(method, path))
126+
127+
for name, counter in counters:
128+
logger.debug("Query {:3} times using {:.2f}s {}".format(
129+
counter.counter, counter.time, name)
130+
)
131+
132+
133+
def _get_request_user():
134+
current_request = get_current_request()
135+
if current_request and current_request.user and current_request.user.is_authenticated:
136+
return current_request.user
137+
138+
139+
@receiver(pre_save)
140+
def on_create_set_creator(sender, instance=None, **kwargs):
141+
if getattr(instance, '_ignore_auto_creator', False):
142+
return
143+
if not hasattr(instance, 'creator') or instance.creator:
144+
return
145+
instance.creator = _get_request_user()
146+
if hasattr(instance, 'dept_belong') and instance.creator:
147+
instance.dept_belong = instance.creator.dept
148+
149+
150+
@receiver(pre_save)
151+
def on_update_set_modifier(sender, instance=None, created=False, **kwargs):
152+
if getattr(instance, '_ignore_auto_modifier', False):
153+
return
154+
if hasattr(instance, 'modifier'):
155+
instance.modifier = _get_request_user()
156+
157+
158+
if settings.DEBUG_DEV:
159+
request_finished.connect(on_request_finished_logging_db_query)

0 commit comments

Comments
 (0)