48 votes

django : Objectif de django.utils.functional.SimpleLazyObject ?

J'ai rencontré un problème lorsque j'ai assigné request.user à une variable appelée prior_user puis a essentiellement authentifié l'utilisateur, puis a vérifié pour voir si request.user != prior_user . Je m'attendais à ce qu'ils ne soient pas les mêmes et que prior_user doit contenir "AnonymousUser". À ma grande surprise, ils étaient identiques.

Exemple de code :

prior_user = request.user   # request object, obtained froma  view
authenticate_user(request)   # some function that authenticates
print prior_user.username != request.user.username   # returns False i.e.they are the same!

J'ai ensuite découvert que prior_user contient en fait une instance de django.utils.functional.SimpleLazyObject. Je suppose donc qu'il s'agit d'une sorte de recherche paresseuse, c'est-à-dire que la valeur de prior_user n'est pas recherchée avant d'être réellement utilisée. En regardant le code source, je ne peux pas le confirmer.

Quelqu'un ayant une expérience de django peut me dire ce qui se passe et pourquoi c'est nécessaire ?

Cela me laisse un peu perplexe, car l'instruction d'affectation habituelle ne fonctionne pas comme je l'attends et qu'est-ce qui se passe d'autre dans Django qui se comporte ainsi ? Je n'ai pas non plus vu cette description dans la docs .

Alors, quelqu'un ayant une connaissance super humaine de django peut apporter un peu de clarté ?

109voto

Chris Pratt Points 53859

El auth ajoute un user de l'attribut request qui est une instance de SimpleLazyObject . SimpleLazyObject qui est lui-même une sous-classe de LazyObject . LazyObject est, comme décrit par le code actuel :

Une enveloppe pour une autre classe qui peut être utilisée pour retarder l'instanciation de la classe enveloppée.

SimpleLazyObject ne fait que définir cette classe (la _wrapped l'attribut LazyObject ) via une méthode passée, dans ce cas, get_user . Voici le code de cette méthode :

def get_user(request):
    if not hasattr(request, '_cached_user'):
        request._cached_user = auth.get_user(request)
    return request._cached_user

En soi, ce n'est qu'une enveloppe autour de auth.get_user qui permet une sorte de mécanisme de mise en cache. Voici donc ce qui est finalement exécuté :

def get_user(request):
    from django.contrib.auth.models import AnonymousUser
    try:
        user_id = request.session[SESSION_KEY]
        backend_path = request.session[BACKEND_SESSION_KEY]
        backend = load_backend(backend_path)
        user = backend.get_user(user_id) or AnonymousUser()
    except KeyError:
        user = AnonymousUser()
    return user

Donc, tout ce qui se passe vraiment ici est que request.user est ambiguë jusqu'à ce qu'elle soit réellement utilisée pour quelque chose. C'est important, car cela lui permet de s'adapter en fonction de l'environnement de travail. actuel statut d'authentification. Si vous accédez à une propriété de celui-ci antes de vous vous authentifiez, il renvoie une instance AnonymousUser mais si vous vous authentifiez et y accédez, il renvoie une instance de User .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X