#python #django
Вопрос:
@property def get_maca(self, request): if request.user.name == "example": return self
Я хочу сделать что-то подобное. Если имя пользователя является примером, верните этот объект.
Как получить доступ к такому запросу?
Комментарии:
1. Ты не можешь. База данных (модель) не имеет понятия о запросе.
2. Вам нужно передать его в качестве аргумента, поэтому вы не можете его использовать
@property
. Но мне кажется, что это плохая практика. Как упоминал @Selcuk, модели не имеют понятия о логике представлений и не должны беспокоиться о ней. Если вам что-то нужно из запроса, извлеките это в своем представлении и передайте методу модели
Ответ №1:
Стандартный способ-передать запрос или, в вашем случае, просто объект пользователя, от представления/маршрутизатора вплоть до моделей.
Это очень быстро выходит из-под контроля в более крупном проекте, поэтому мой подход заключается в использовании локального потока для сохранения некоторого контекста запроса, который мне нравится иметь доступным во всем проекте. Локальное хранилище потоков будет хранить данные, доступные внутри одного потока, без доступа к ним из других потоков — отлично, если вы собираетесь запускать приложение 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