request.user возвращает SimpleLazyObject, как мне его "разбудить"?

У меня есть следующий метод:

def _attempt(actor):
    if actor.__class__ != User:
        raise TypeError

Который называется из вида:

self.object.attempt(self.request.user)

Как видите, метод _attempt ожидает, что actor будет иметь тип django.contrib.auth.models.UserОднако объект, как представляется, имеет тип django.utils.functional.SimpleLazyObject, Почему это так? И что более важно, как я могу преобразовать LazyObject (который, по-видимому, является своего рода оболочкой для объекта User) в User объект?

Больше информации о Request.user доступно здесь: https://docs.djangoproject.com/en/dev/ref/request-response/ Эта документация указывает на request.user должен быть User объект...

====== после редактирования =====

У меня есть следующий метод сейчас:

def _attempt(obj, action, actor, msg): 
    actor.is_authenticated() 
    if isinstance(actor, LazyObject): 
        print type(actor) 

Я передаю пользователя, однако if условие все еще выполняется, актер по-прежнему LazyObject, Почему это так?

7 ответов

Решение

Смотрите мой ответ на похожий вопрос.

Джанго ленивый груз request.user так что это может быть либо User или же AnonymousUser в зависимости от состояния аутентификации. Он только "просыпается" и возвращает соответствующий класс, когда к нему обращаются к атрибуту. К несчастью, __class__ не считается, потому что это примитивный атрибут класса. Есть случаи, когда вам может понадобиться знать, что это на самом деле SimpleLazyObject типа, и поэтому было бы неправильно проксировать его на User или же AnonymousUser,

Короче говоря, вы просто не можете сделать это сравнение, как оно есть. Но чего вы действительно пытаетесь достичь здесь? Если вы пытаетесь проверить, является ли это User или же AnonymousUserесть request.user.is_authenticated() для этого, например.

Однако, как правило, вы не должны злоупотреблять печатанием утки. Параметр всегда должен быть определенного типа или подтипа (User или же UserSubClass), хотя это не должно быть. В противном случае вы получите запутанный и хрупкий код.

Это должно сделать это:

# 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 не являются кражами!)

user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user

Тогда вы используете user вместо request.user,

Это похоже на ответ UsAaR33, но однострочник лучше для преобразования объекта.

Для любого, кто хочет написать "маленький" юнит-тест для вашего кода, вы можете создать упакованный 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='jacob@…',
    password='top_secret',
)

factory = RequestFactory()
request = factory.get('/')
request.user = SimpleLazyObject(lambda: user)

Увидеть:

Это может быть полезно другим и немного чище.

Метод python isinstance(instance, class) возвращает, если содержащийся экземпляр SimpleLazyObject относится к предоставленному классу.

if isinstance(request.user, User):
    user = request.user

Измените свой код вот так, и проблем быть не должно:

from copy import deepcopy

def _attempt(actor):
    actor = deepcopy(actor)
    if actor.__class__ != User:
        raise TypeError

Это схема этого auth_userстол в Джанго -

      id
password
last_login
is_superuser
username
last_name
email
is_staff
is_active
date_joined
first_name

Теперь, если вы хотите idпиши как-

      req.user.id

и если ты хочешь usernameпиши как-

      req.user.username
Другие вопросы по тегам