2012-07-03 3 views
50

Ho il seguente metodo:request.user restituisce un oggetto SimpleLazyObject, come posso "attivarlo"?

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

che viene chiamato da una visione:

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

Come si può vedere, il metodo _attempt si aspetta che l'attore sia il tipo django.contrib.auth.models.User, tuttavia l'oggetto sembra essere di tipo django.utils.functional.SimpleLazyObject. Perché è così? E ancora più importante, come posso convertire il LazyObject (che apparentemente è una specie di wrapper per un oggetto User) in un oggetto User?

Maggiori informazioni Request.user è disponibile qui: https://docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.user Questa documentazione sembra indicare la request.user dovrebbe essere un oggetto User ...

====== ===== post-edit

ho il seguente metodo ora:

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

sto passando un utente, ma la condizione if è ancora vero, l'attore è ancora una LazyObject. Perché è così?

risposta

33

Vedere my answer on a similar question.

Django lazy load request.user in modo che possa essere sia User o AnonymousUser a seconda dello stato di autenticazione. Si "riattiva" e restituisce la classe appropriata quando si accede a un attributo. Sfortunatamente, __class__ non conta perché è un attributo di classe primitivo. Ci sono occasioni in cui potresti dover sapere che si tratta in realtà di un tipo SimpleLazyObject e che quindi sarebbe errato impostarlo su User o AnonymousUser.

Lungo e breve, non è possibile effettuare questo confronto come si ha. Ma, cosa stai cercando di ottenere qui ? Se stai cercando di verificare se si tratta di un numero User o AnonymousUser, ad esempio, c'è lo request.user.is_authenticated().

Come regola generale, non dovresti abusare della digitazione anatra. Un parametro dovrebbe sempre essere un tipo o sottotipo particolare (User o UserSubClass), anche se non è avere. Altrimenti, si finisce con codice confuso e fragile.

+2

Grazie per la risposta, Chris. In effetti, sto cercando di verificare se si tratta di un utente o di un utente anonimo. Ho il seguente metodo ora: 'def _attempt (obj, azione, attore, MSG): actor.is_authenticated() se isinstance (attore, LazyObject): tipo di stampa (attore)' Sono passando un utente, tuttavia se la condizione if è ancora vera, l'attore è ancora un LazyObject. Perché è così? – Himerzi

+0

Mi rendo conto che potrei fare una prova: su actor.isauthenticated() e quindi prendere un AttributeException, che indicherebbe che l'attore non ha alcun metodo autenticato (e quindi non è un utente). Ma sono ancora un po 'perplesso sul motivo per cui il frammento di codice nel mio commento precedente non funziona. – Himerzi

+0

È * funzionante, in un certo senso; '__class__' restituisce esattamente ciò che dovrebbe restituire,' SimpleLazyObject', perché è quello che la classe * è *. –

13

Questo dovrebbe farlo:

# handle django 1.4 pickling bug 
if hasattr(user, '_wrapped') and hasattr(user, '_setup'): 
    if user._wrapped.__class__ == object: 
     user._setup() 
    user = user._wrapped 

ho dovuto scrivere questo così ho potuto aggiungere un utente al dizionario sessione. (SimpleLazyObjects non sono serializzabili!)

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

quindi si utilizza user invece di request.user.

Questo è simile alla risposta di UsAaR33, ma un one-liner è più adatto per la conversione dell'oggetto.

+3

È simile ma non tenta di chiamare '_setup()' sull'oggetto utente se la parte '_wrapped' non è inizializzata correttamente. Penso che la risposta di UsAaR33 sia preferibile per questo motivo. – MichaelJones

0

Per chiunque desideri scrivere un "piccolo" errore non valido per il proprio codice, è possibile generare uno User impacchettato e inserirlo all'interno di una richiesta.

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) 

See: