Request.user возвращает объект SimpleLazyObject, как его "разбудить"?
У меня есть следующий метод:
def _attempt(actor):
if actor.__class__ != User:
raise TypeError
Что вызывается из представления:
self.object.attempt(self.request.user)
Как вы можете видеть, метод _attempt предполагает, что актер будет иметь тип django.contrib.auth.models.User
, однако объект выглядит как тип django.utils.functional.SimpleLazyObject
. Почему это так? И что еще более важно, как я могу преобразовать LazyObject
(который, видимо, является своего рода оболочкой для объекта User) в объект User
?
Дополнительная информация о Request.user
доступна здесь: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.user В этой документации указывается, что Request.user
должен быть User
объект...
====== после редактирования =====
Теперь у меня есть следующий метод:
def _attempt(obj, action, actor, msg):
actor.is_authenticated()
if isinstance(actor, LazyObject):
print type(actor)
Я передаю пользователя, однако условие if
по-прежнему истинно, актер по-прежнему остается LazyObject
. Почему это так?
Ответы
Ответ 1
См. мой ответ по аналогичному вопросу.
Django lazy load request.user
, чтобы он мог быть либо User
, либо AnonymousUser
в зависимости от состояния аутентификации. Он только "просыпается" и возвращает соответствующий класс, когда к нему обращается атрибут. К сожалению, __class__
не учитывается, потому что это примитивный атрибут класса. Там, где вам может понадобиться знать, что это действительно тип SimpleLazyObject
, и поэтому было бы неправильно проксировать его на User
или AnonymousUser
.
Длинные и короткие, вы просто не можете сделать это сравнение, как у вас есть. Но чего вы на самом деле пытаетесь достичь здесь? Если вы пытаетесь проверить, есть ли User
или AnonymousUser
, там request.user.is_authenticated()
для этого, например.
Как правило, вы не должны злоупотреблять печатью утки. Параметр всегда должен быть особенно типом или подтипом (User
или UserSubClass
), хотя это необязательно. В противном случае вы получите путаный и хрупкий код.
Ответ 2
Это должно сделать это:
# handle django 1.4 pickling bug
if hasattr(user, '_wrapped') and hasattr(user, '_setup'):
if user._wrapped.__class__ == object:
user._setup()
user = user._wrapped
Мне пришлось написать это, чтобы добавить пользователя в словарь сеанса. (SimpleLazyObjects не подбираются!)
Ответ 3
user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user
Затем вы используете user
вместо request.user
.
Это похоже на ответ UsAaR33, но однострочный режим лучше для преобразования объекта.
Ответ 4
Для тех, кто хочет написать неудачный "маленький" unittest для вашего кода, вы можете создать завернутый User
и наполнить его внутри запроса.
from django.contrib.auth import get_user_model
from django.test import RequestFactory
from django.utils.functional import SimpleLazyObject
user = get_user_model().objects.create_user(
username='jacob',
email='[email protected]…',
password='top_secret',
)
factory = RequestFactory()
request = factory.get('/')
request.user = SimpleLazyObject(lambda: user)
См: