W mojej aplikacji Django muszę zacząć uruchamiać kilka okresowych zadań w tle, gdy użytkownik się loguje, i przestać je uruchamiać, gdy użytkownik się wyloguje, więc szukam eleganckiego sposobu
- otrzymywać powiadomienia o logowaniu / wylogowaniu użytkownika
- zapytaj o stan logowania użytkownika
Z mojej perspektywy idealnym rozwiązaniem byłoby
- sygnał wysłany przez każdy
django.contrib.auth.views.login
i... views.logout
- metoda
django.contrib.auth.models.User.is_logged_in()
analogiczna do... User.is_active()
lub... User.is_authenticated()
Django 1.1.1 tego nie ma i niechętnie poprawiam źródła i dodam je (zresztą nie wiem jak to zrobić).
Jako rozwiązanie tymczasowe dodałem is_logged_in
do modelu UserProfile pole boolowskie, które jest domyślnie wyczyszczone, jest ustawiane przy pierwszym wejściu użytkownika na stronę docelową (zdefiniowane przez LOGIN_REDIRECT_URL = '/'
) i jest odpytywane w kolejnych żądaniach. Dodałem go do UserProfile, więc nie muszę wyprowadzać i dostosowywać wbudowanego modelu użytkownika tylko do tego celu.
Nie podoba mi się to rozwiązanie. Jeśli użytkownik wyraźnie kliknie przycisk wylogowania, mogę wyczyścić flagę, ale w większości przypadków użytkownicy po prostu opuszczają stronę lub zamykają przeglądarkę; Usunięcie flagi w takich przypadkach nie wydaje mi się proste. Poza tym (jest to raczej szukanie jasności modelu danych), is_logged_in
nie należy do UserProfile, ale do modelu User.
Czy ktoś może pomyśleć o alternatywnych podejściach?
Odpowiedzi:
Możesz użyć takiego sygnału (umieściłem mój w models.py)
from django.contrib.auth.signals import user_logged_in def do_stuff(sender, user, request, **kwargs): whatever... user_logged_in.connect(do_stuff)
Zobacz dokumentację django: https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals i tutaj http://docs.djangoproject.com/en/dev/ tematy / sygnały /
źródło
models.py
zamiast tego sugeruję umieszczenie kodusignals.py
i automatyczne zaimportowanie go do__init__.py
pliku modułów .Oprócz odpowiedzi @PhoebeB: możesz również użyć
@receiver
dekoratora w ten sposób:from django.contrib.auth.signals import user_logged_in from django.dispatch import receiver @receiver(user_logged_in) def post_login(sender, user, request, **kwargs): ...do your stuff..
A jeśli umieścisz to
signals.py
w katalogu swojej aplikacji, dodaj to doapps.py
:class AppNameConfig(AppConfig): ... def ready(self): import app_name.signals
źródło
Jedną z opcji może być zawinięcie widoków logowania / wylogowania Django własnymi. Na przykład:
from django.contrib.auth.views import login, logout def my_login(request, *args, **kwargs): response = login(request, *args, **kwargs) #fire a signal, or equivalent return response def my_logout(request, *args, **kwargs): #fire a signal, or equivalent return logout(request, *args, **kwargs)
Następnie używasz tych widoków w swoim kodzie, a nie w Django, i voila.
Jeśli chodzi o sprawdzanie statusu logowania, jest to całkiem proste, jeśli masz dostęp do obiektu żądania; po prostu sprawdź atrybut użytkownika żądania, aby zobaczyć, czy jest to zarejestrowany użytkownik, czy anonimowy użytkownik i bingo. Cytując dokumentację Django :
if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users.
Jeśli nie masz dostępu do obiektu żądania, określenie, czy bieżący użytkownik jest zalogowany, będzie trudne.
Edytować:
Niestety, nigdy nie będziesz w stanie uzyskać
User.is_logged_in()
funkcjonalności - jest to ograniczenie protokołu HTTP. Jeśli jednak przyjmiesz kilka założeń, możesz być w stanie zbliżyć się do tego, czego chcesz.Po pierwsze, dlaczego nie możesz uzyskać tej funkcji? Cóż, nie możesz odróżnić kogoś, kto zamknął przeglądarkę, a kimś, kto spędził trochę czasu na stronie przed pobraniem nowej. Nie ma sposobu, aby stwierdzić przez HTTP, kiedy ktoś faktycznie opuści witrynę lub zamknie przeglądarkę.
Masz więc dwie opcje, które nie są idealne:
unload
zdarzenia JavaScript, aby wychwycić, kiedy użytkownik opuszcza stronę. Musisz jednak napisać ostrożną logikę, aby upewnić się, że nie wylogowujesz użytkownika, gdy nadal nawiguje on po Twojej witrynie.Te rozwiązania są niechlujne i nie są idealne, ale niestety są najlepsze, co możesz zrobić.
źródło
is_logged_in
rzeczy zbyt dobrze (przepraszam, myślę, że nie spisałem się dobrze czytając post), ale zaktualizowałem odpowiedź, aby zaoferować, jaką mogę pomóc w tej dziedzinie . Niestety jest to trochę niemożliwy problem.szybkim rozwiązaniem byłoby umieszczenie w _ _ init _ _.py swojej aplikacji następującego kodu:
from django.contrib.auth.signals import user_logged_in from django.dispatch import receiver @receiver(user_logged_in) def on_login(sender, user, request, **kwargs): print('User just logged in....')
źródło
Jedynym niezawodnym sposobem (który również wykrywa, kiedy użytkownik zamknął przeglądarkę) jest aktualizacja jakiegoś
last_request
pola za każdym razem, gdy użytkownik ładuje stronę.Możesz również mieć okresowe żądanie AJAX, które pinguje serwer co x minut, jeśli użytkownik ma otwartą stronę.
Następnie wykonaj jedno zadanie w tle, które pobierze listę ostatnich użytkowników, utwórz dla nich zadania i wyczyść zadania dla użytkowników, których nie ma na tej liście.
źródło
Wnioskowanie o wylogowaniu, w przeciwieństwie do wyraźnego kliknięcia przycisku (czego nikt nie robi), oznacza wybranie ilości czasu bezczynności, która jest równoznaczna z „wylogowaniem”. phpMyAdmin używa domyślnie 15 minut, niektóre strony bankowe zajmują tylko 5 minut.
Najprostszym sposobem wdrożenia tego byłoby zmiana czasu życia pliku cookie. Możesz to zrobić dla całej witryny, określając
settings.SESSION_COOKIE_AGE
. Alternatywnie możesz zmienić to dla każdego użytkownika (na podstawie dowolnego zestawu kryteriów), używającHttpResponse.setcookie()
. Możesz scentralizować ten kod, tworząc własną wersjęrender_to_response()
i ustawiając okres istnienia dla każdej odpowiedzi.źródło
Zgrubny pomysł - możesz do tego użyć oprogramowania pośredniczącego. To oprogramowanie pośredniczące może przetwarzać żądania i uruchamiać sygnał, gdy żądany jest odpowiedni adres URL. Może również przetwarzać odpowiedzi i sygnał pożaru, gdy dane działanie faktycznie się powiedzie.
źródło