Оптимизация N+1 запросов к ролям пользователей через select_related в middleware
This commit is contained in:
@@ -33,6 +33,24 @@ class TenantAdminAccessMiddleware:
|
|||||||
}, status=403)
|
}, status=403)
|
||||||
|
|
||||||
def __call__(self, request):
|
def __call__(self, request):
|
||||||
|
# Оптимизация: загружаем роль пользователя один раз для всего запроса
|
||||||
|
if hasattr(request, 'user') and request.user.is_authenticated:
|
||||||
|
schema_name = getattr(connection, 'schema_name', 'public')
|
||||||
|
# Только для tenant схем и CustomUser загружаем роль с select_related
|
||||||
|
if schema_name != 'public':
|
||||||
|
from accounts.models import CustomUser
|
||||||
|
if isinstance(request.user, CustomUser):
|
||||||
|
# Проверяем, не загружена ли уже роль
|
||||||
|
if not hasattr(request.user, '_role_prefetched'):
|
||||||
|
try:
|
||||||
|
# Загружаем пользователя с ролью через select_related
|
||||||
|
request.user = CustomUser.objects.select_related(
|
||||||
|
'tenant_role__role'
|
||||||
|
).get(pk=request.user.pk)
|
||||||
|
request.user._role_prefetched = True
|
||||||
|
except CustomUser.DoesNotExist:
|
||||||
|
pass
|
||||||
|
|
||||||
# Проверяем, это admin URL?
|
# Проверяем, это admin URL?
|
||||||
if request.path.startswith('/admin/'):
|
if request.path.startswith('/admin/'):
|
||||||
# Импортируем здесь чтобы избежать circular imports
|
# Импортируем здесь чтобы избежать circular imports
|
||||||
|
|||||||
@@ -110,8 +110,22 @@ class RoleService:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_user_role(user):
|
def get_user_role(user):
|
||||||
"""Получить роль пользователя в текущем тенанте"""
|
"""
|
||||||
|
Получить роль пользователя в текущем тенанте.
|
||||||
|
Оптимизация: использует уже загруженные данные если есть select_related.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
|
# Проверяем, есть ли уже загруженная роль через select_related
|
||||||
|
if hasattr(user, 'tenant_role'):
|
||||||
|
# Проверяем, что tenant_role загружен (а не RelatedObjectDoesNotExist)
|
||||||
|
try:
|
||||||
|
user_role = user.tenant_role
|
||||||
|
if user_role.is_active and hasattr(user_role, 'role'):
|
||||||
|
return user_role.role
|
||||||
|
except UserRole.DoesNotExist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Если нет prefetch - делаем запрос
|
||||||
user_role = UserRole.objects.get(user=user, is_active=True)
|
user_role = UserRole.objects.get(user=user, is_active=True)
|
||||||
return user_role.role
|
return user_role.role
|
||||||
except UserRole.DoesNotExist:
|
except UserRole.DoesNotExist:
|
||||||
|
|||||||
Reference in New Issue
Block a user