我正在一个带有Postgres的示例django应用程序上测试我的数据库查询中间件(姜戈博士)。应用程序是炊具样板。我使用中间件的目标只是记录所有数据库查询的用户ID。使用Python3.9和Django3.2.13。我的中间件代码如下:
# Middleware code
import logging
import django
from django.db import connection
django_version = django.get_version()
logger = logging.getLogger(__name__)
class Logger:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
with connection.execute_wrapper(QueryWrapper(request)):
return self.get_response(request)
class QueryWrapper:
def __init__(self, request):
self.request = request
def __call__(self, execute, sql, params, many, context):
# print(self.request.user)
return execute(sql, params, many, context)如果print(self.request.user.id)被注释掉,一切都会正常运行。但是,我发现取消注释或与user字段在self.request对象中的任何类型的交互都会导致递归错误:
RecursionError at /about/
maximum recursion depth exceeded
Request Method: GET
Request URL: http://127.0.0.1:8000/about/
Django Version: 3.2.13
Exception Type: RecursionError
Exception Value:
maximum recursion depth exceeded
Exception Location: /opt/homebrew/lib/python3.9/site-packages/django/db/models/sql/query.py, line 192, in __init__
Python Executable: /opt/homebrew/opt/python@3.9/bin/python3.9
Python Version: 3.9.13在错误页面中,后面是以下错误的多次重复:
During handling of the above exception ('SessionStore' object has no attribute '_session_cache'), another exception occurred:
/opt/homebrew/lib/python3.9/site-packages/django/contrib/sessions/backends/base.py, line 233, in _get_session
return self._session_cache …
During handling of the above exception ('SessionStore' object has no attribute '_session_cache'), another exception occurred:
/opt/homebrew/lib/python3.9/site-packages/django/contrib/sessions/backends/base.py, line 233, in _get_session
return self._session_cache …通过咨询其他这样的帖子,访问user字段似乎应该工作得很好。我已经检查了django_session表的存在,我的中间件也位于我的中间件的最底层(包括"django.contrib.sessions.middleware.SessionMiddleware"和"django.contrib.auth.middleware.AuthenticationMiddleware")。
这里怎么了?
发布于 2022-05-24 04:00:14
编写self.request.user时会发生以下情况
request是否具有属性_cached_user,如果存在缓存的用户,则返回缓存的用户,如果没有,则在请求中调用auth.get_user。如前所述,除非缓存命中,否则此进程将导致数据库查询。
使用数据库工具,您已经在数据库查询周围安装了一个包装器,问题是这个包装器本身正在尝试进行更多的查询(试图获取当前用户),从而导致它调用自己。一种解决方案是在安装包装器功能之前获取当前用户:
class Logger:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
_user_authenticated = request.user.is_authenticated # Making sure user is fetched (Lazy object)
with connection.execute_wrapper(QueryWrapper(request)):
return self.get_response(request)
class QueryWrapper:
def __init__(self, request):
self.request = request
def __call__(self, execute, sql, params, many, context):
print(self.request.user)
return execute(sql, params, many, context)https://stackoverflow.com/questions/72356939
复制相似问题