Как получить доступ к запросу в models.py, django
@property
def get_maca(self, request):
if request.user.name == "example":
return self
Я хочу сделать что-то вроде этого. Если имя пользователя является примером, вернуть этот объект.
Как получить доступ к запросу в таком виде?
Стандартным способом является передача запроса, или в вашем случае просто объекта пользователя, от представления/маршрутизатора вплоть до моделей.
В больших проектах это очень быстро выходит из-под контроля, поэтому я использую метод thread local для сохранения некоторого контекста запроса, который я хочу иметь доступным для всего проекта. Локальное хранилище потоков позволяет сохранять данные внутри одного потока, без доступа к ним из других потоков - отлично, если вы собираетесь запустить приложение Django на рабочем сервере.
Начните с локального хранилища:
from threading import local
_active_user = local()
def activate_user(user):
if not user:
return
_active_user.value = user
def deactivate_user():
if hasattr(_active_user, "value"):
del _active_user.value
def get_user():
"""Returns `(is_anonymous, user)` ."""
active_user = getattr(_active_user, "value", None)
if active_user and active_user is not AnonymousUser:
try:
return False, active_user
except AttributeError:
pass
return True, None
Теперь все в порядке, вы можете использовать это вручную. Вызвав activate_user
, вы сможете вызывать get_user
в любом месте вашего проекта. Однако это чревато ошибками - если вы забудете вызвать deactivate_user
, объект пользователя все еще будет доступен для следующего приходящего запроса.
Остальная часть ответа - показать, как сделать все автоматическим.
Давайте сначала сделаем промежуточное ПО для очистки, вызывая deactivate_user
после каждого запроса.
class ThreadCleanupMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
# Executed for each request/response after
# the view is called.
deactivate_user()
return response
Добавьте путь к ThreadCleanupMiddleware
в конец вашего settings.MIDDLEWARE
списка.
Завершите работу миксином представления, который автоматически активирует пользователя (это для представлений на основе классов; если вы используете функциональные представления, это будет декоратор):
class ContextViewSetMixin:
def initial(self, request, *args, **kwargs):
super().initial(request, *args, **kwargs)
if request.user.is_authenticated:
activate_user(request.user)
class ContextModelViewSet(ContextViewSetMixin, viewsets.ModelViewSet):
pass
def form_valid(self):
self.request.user == "example"
return super().form_valid()