Подтвердить что ты не робот

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. Почему это так?

4b9b3361

Ответ 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)

См: