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)
Увидеть:
https://github.com/django/django/blob/master/tests/utils_tests/test_lazyobject.py для текущих тестов на Lazy Objects.
https://docs.djangoproject.com/en/dev/topics/testing/advanced/ для получения последней информации о
RequestFactory
,
Это может быть полезно другим и немного чище.
Метод 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