私のDjangoアプリでは、ユーザーがログインするといくつかの定期的なバックグラウンドジョブの実行を開始し、ユーザーがログアウトすると実行を停止する必要があるため、エレガントな方法を探しています
私の観点から、理想的なソリューションは
Django.contrib.auth.views.login
_および_... views.logout
_によって送信されるシグナルDjango.contrib.auth.models.User.is_logged_in()
または... User.is_active()
に類似したメソッド... User.is_authenticated()
Django 1.1.1にはそれがなく、ソースにパッチを適用して追加することに消極的です(とにかくそれを行う方法がわかりません)。
一時的な解決策として、ユーザープロファイルモデルに_is_logged_in
_ブールフィールドを追加しました。これはデフォルトでクリアされ、ユーザーがランディングページに初めてアクセスしたときに設定され(_LOGIN_REDIRECT_URL = '/'
_で定義)、クエリされますその後のリクエスト。それをUserProfileに追加したので、その目的のためだけに組み込みのUserモデルから派生してカスタマイズする必要はありません。
私はこの解決策が好きではありません。ユーザーが明示的にログアウトボタンをクリックすると、フラグをクリアできますが、ほとんどの場合、ユーザーはページを離れるか、ブラウザーを閉じます。これらの場合にフラグをクリアすることは、私には簡単ではありません。 (ただし、それはむしろデータモデルの明快さの選択です)、_is_logged_in
_はUserProfileではなく、Userモデルに属します。
誰もが代替アプローチを考えることができますか?
このような信号を使用できます(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)
Django docs: https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-Django.contrib.auth.signals を参照してくださいそしてここ http://docs.djangoproject.com/en/dev/topics/signals/
1つのオプションは、Djangoのログイン/ログアウトビューを独自のものでラップすることです。例えば:
_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)
_
次に、Djangoのビューではなく、これらのビューをコードで使用します。
ログインステータスのクエリに関しては、リクエストオブジェクトにアクセスできれば非常に簡単です。リクエストのユーザー属性をチェックして、それらが登録ユーザーか匿名ユーザーか、ビンゴかを確認します。 Django documentation を引用するには:
_if request.user.is_authenticated():
# Do something for logged-in users.
else:
# Do something for anonymous users.
_
要求オブジェクトにアクセスできない場合、現在のユーザーがログインしているかどうかを判断するのは困難です。
編集:
残念ながら、User.is_logged_in()
機能を取得することはできません-これはHTTPプロトコルの制限です。ただし、いくつかの仮定を行うと、望むものに近づくことができる場合があります。
まず、なぜその機能を利用できないのですか?さて、あなたは誰かがブラウザを閉じているのか、誰かが新しいものを取得する前にページでしばらく過ごしているのかを区別することはできません。誰かが実際にサイトを離れたときやブラウザを閉じたときにHTTPで通知する方法はありません。
したがって、完璧ではない2つのオプションがあります。
unload
イベントを使用して、ユーザーがページを離れたときにキャッチします。ただし、ユーザーがyourサイトをナビゲートしているときにユーザーをログアウトさせないように、慎重なロジックを記述する必要があります。これらのソリューションは面倒で理想的ではありませんが、残念ながらあなたができる最善の方法です。
@PhoebeBの答えに加えて、次のように@receiver
デコレーターを使用することもできます。
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..`
そして、アプリのディレクトリのsignals.py
に配置した場合、これをapp.py
に追加します。
def ready(self):
import app_name.signals`
明示的にボタンをクリックするのではなく(誰もクリックしない)、ログアウトを推測するということは、「ログアウト」に相当するアイドル時間を選択することを意味します。 phpMyAdminはデフォルトの15分を使用しますが、一部の銀行サイトではわずか5分しか使用しません。
これを実装する最も簡単な方法は、cookie-lifetimeを変更することです。 _settings.SESSION_COOKIE_AGE
_ を指定することで、サイト全体でこれを行うことができます。または、 HttpResponse.setcookie()
を使用して、ユーザーごとに(任意の基準セットに基づいて)変更できます。独自のバージョンの render_to_response()
を作成し、各応答の有効期間を設定することにより、このコードを集中化できます。
唯一の信頼できる方法(ユーザーがブラウザを閉じたことを検出する方法)は、いくつかのlast_request
フィールドは、ユーザーがページを読み込むたびに表示されます。
また、ユーザーがページを開いている場合に、x分ごとにサーバーにpingを送信する定期的なAJAX要求を出すこともできます。
次に、最近のユーザーのリストを取得する単一のバックグラウンドジョブを作成し、それらのジョブを作成し、そのリストに存在しないユーザーのジョブをクリアします。
大まかなアイデア-これにはミドルウェアを使用できます。このミドルウェアは、リクエストを処理し、関連するURLがリクエストされるとシグナルを発することができます。また、指定されたアクションが実際に成功したときに、応答と発火信号を処理することもできます。
これに対する簡単な解決策は、アプリの_ _ init _ _.pyに次のコードを配置することです。
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....')