In meiner Django-App muss ich einige regelmäßige Hintergrundjobs ausführen, wenn sich ein Benutzer anmeldet, und sie nicht mehr ausführen, wenn sich der Benutzer abmeldet. Daher suche ich nach einer eleganten Möglichkeit, dies zu tun
- Benachrichtigung über ein Benutzer-Login / Logout
- Benutzeranmeldestatus abfragen
Aus meiner Sicht wäre die ideale Lösung
- ein von jedem
django.contrib.auth.views.login
und gesendetes Signal... views.logout
- eine Methode
django.contrib.auth.models.User.is_logged_in()
, analog zu... User.is_active()
oder... User.is_authenticated()
Django 1.1.1 hat das nicht und ich zögere es, die Quelle zu patchen und hinzuzufügen (ich bin mir sowieso nicht sicher, wie ich das machen soll).
Als vorübergehende Lösung habe ich is_logged_in
dem UserProfile-Modell ein boolesches Feld hinzugefügt , das standardmäßig gelöscht wird, beim ersten Aufrufen der Zielseite durch den Benutzer festgelegt wird (definiert durch LOGIN_REDIRECT_URL = '/'
) und in nachfolgenden Anforderungen abgefragt wird. Ich habe es zu UserProfile hinzugefügt, damit ich das integrierte Benutzermodell nicht nur für diesen Zweck ableiten und anpassen muss.
Ich mag diese Lösung nicht. Wenn der Benutzer explizit auf die Schaltfläche zum Abmelden klickt, kann ich das Flag löschen. In den meisten Fällen verlassen Benutzer jedoch nur die Seite oder schließen den Browser. Das Löschen der Flagge in diesen Fällen scheint mir nicht einfach zu sein. Außerdem (das ist aber eher Datenmodell-Klarheit, Nitpicking) is_logged_in
gehört nicht in das UserProfile, sondern in das User-Modell.
Kann sich jemand alternative Ansätze vorstellen?
Antworten:
Sie können ein solches Signal verwenden (ich habe mein Signal in models.py eingefügt)
from django.contrib.auth.signals import user_logged_in def do_stuff(sender, user, request, **kwargs): whatever... user_logged_in.connect(do_stuff)
Siehe Django-Dokumente: https://docs.djangoproject.com/de/dev/ref/contrib/auth/#module-django.contrib.auth.signals und hier http://docs.djangoproject.com/en/dev/ Themen / Signale /
quelle
models.py
stattdessen einzugeben, schlage ich vor, den Codesignals.py
einzufügen und ihn automatisch in die__init__.py
Datei des Moduls zu importieren .Zusätzlich zu @PhoebeB Antwort: Sie können auch
@receiver
Dekorateur wie folgt verwenden :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..`
Und wenn Sie es in
signals.py
Ihr App-Verzeichnis einfügen, fügen Sie dies hinzu zuapp.py
:def ready(self): import app_name.signals`
quelle
Eine Möglichkeit könnte darin bestehen, die Anmelde- / Abmeldeansichten von Django mit Ihren eigenen zu versehen. Zum Beispiel:
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)
Sie verwenden diese Ansichten dann in Ihrem Code anstelle von Djangos und voila.
In Bezug auf die Abfrage des Anmeldestatus ist es ziemlich einfach, wenn Sie Zugriff auf das Anforderungsobjekt haben. Überprüfen Sie einfach das Benutzerattribut der Anfrage, um festzustellen, ob es sich um einen registrierten Benutzer oder einen anonymen Benutzer handelt, und Bingo. So zitieren Sie die Django-Dokumentation :
if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users.
Wenn Sie keinen Zugriff auf das Anforderungsobjekt haben, ist es schwierig festzustellen, ob der aktuelle Benutzer angemeldet ist.
Bearbeiten:
Leider werden Sie nie in der Lage sein,
User.is_logged_in()
Funktionen zu erhalten - dies ist eine Einschränkung des HTTP-Protokolls. Wenn Sie jedoch einige Annahmen treffen, können Sie sich möglicherweise dem nähern, was Sie wollen.Erstens, warum können Sie diese Funktionalität nicht erhalten? Nun, Sie können den Unterschied zwischen jemandem, der den Browser schließt, oder jemandem, der eine Weile auf einer Seite verbringt, bevor er eine neue abruft, nicht erkennen. Über HTTP kann nicht festgestellt werden, wann jemand die Site tatsächlich verlässt oder den Browser schließt.
Sie haben hier also zwei Möglichkeiten, die nicht perfekt sind:
unload
Ereignis von Javascript, um zu erfassen, wann ein Benutzer eine Seite verlässt. Sie müssten jedoch eine sorgfältige Logik schreiben, um sicherzustellen, dass Sie einen Benutzer nicht abmelden, wenn er noch auf Ihrer Website navigiert .Diese Lösungen sind chaotisch und nicht ideal, aber leider das Beste, was Sie tun können.
quelle
is_logged_in
Zeug überhaupt nicht wirklich gut angesprochen (Entschuldigung, ich glaube, ich habe den Beitrag nicht besonders gut gelesen), aber ich habe die Antwort aktualisiert, um anzubieten, was ich in diesem Bereich helfen kann . Das ist leider ein unmögliches Problem.Eine schnelle Lösung hierfür wäre, im _ _ init _ _.py Ihrer App den folgenden Code zu platzieren:
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....')
quelle
Die einzige zuverlässige Möglichkeit (die auch erkennt, wenn der Benutzer den Browser geschlossen hat) besteht darin
last_request
, jedes Mal, wenn der Benutzer eine Seite lädt, ein Feld zu aktualisieren .Sie können auch eine regelmäßige AJAX-Anforderung erhalten, die den Server alle x Minuten anpingt, wenn der Benutzer eine Seite geöffnet hat.
Verfügen Sie dann über einen einzelnen Hintergrundjob, der eine Liste der zuletzt verwendeten Benutzer abruft, Jobs für sie erstellt und die Jobs für Benutzer löscht, die in dieser Liste nicht vorhanden sind.
quelle
Wenn Sie auf das Abmelden schließen, anstatt explizit auf eine Schaltfläche zu klicken (was niemand tut), müssen Sie eine Leerlaufzeit auswählen, die "Abgemeldet" entspricht. phpMyAdmin verwendet einen Standardwert von 15 Minuten, einige Bankseiten benötigen nur 5 Minuten.
Die einfachste Möglichkeit, dies zu implementieren, besteht darin, die Lebensdauer der Cookies zu ändern. Sie können dies für Ihre gesamte Site tun, indem Sie angeben
settings.SESSION_COOKIE_AGE
. Alternativ können Sie es auf Benutzerbasis (basierend auf einem beliebigen Satz von Kriterien) mithilfe von ändernHttpResponse.setcookie()
. Sie können diesen Code zentralisieren, indem Sie eine eigene Version von erstellenrender_to_response()
und die Lebensdauer für jede Antwort festlegen.quelle
Grobe Idee - Sie könnten dafür Middleware verwenden. Diese Middleware kann Anforderungen verarbeiten und ein Signal auslösen, wenn eine relevante URL angefordert wird. Es könnte auch Reaktionen und Feuersignale verarbeiten, wenn eine bestimmte Aktion tatsächlich erfolgreich war.
quelle