2013-08-25 11 views
16

Djangoでは、最後にログインしたユーザーの時間をAuth.User.last_loginで取得できます。これは、ユーザー名/パスワードを使用してユーザーがログインしたときにのみ更新されます。ユーザーがすでにログインしていて、認証情報がCookieに保存されているため、ログインせずにサイトにアクセスできるとします。ユーザーが以前にサイトにアクセスした日時を取得するにはどうすればよいですか。これは、最後の訪問以降に新しいレコードの数を取得するなどのクエリに役立ちます。Django:最終訪問日を取得

+0

https://godjango.com/blog/record-last-access-not- just-last-login /は、ミドルウェアの場合のような特別な検索をしないので、より効率的です。 –

答えて

22

例モデル:全てのログインしているユーザのために実行される

class User(models.Model): 
    last_visit = models.DateTimeField(...) 
    ... 

例ミドルウェア:

from django.utils.timezone import now 

class SetLastVisitMiddleware(object): 
    def process_response(self, request, response): 
     if request.user.is_authenticated(): 
      # Update last visit time after request finished processing. 
      User.objects.filter(pk=request.user.pk).update(last_visit=now()) 
     return response 

広告Dあなたのsettings.pyに新しいミドルウェア:

MIDDLEWARE_CLASSES = (
    ... 
    'path.to.your.SetLastVisitMiddleware', 
    ... 
) 

警告:テストされていませんが、インストールする外部のパッケージを必要とせず、それは、コードの唯一の5行ですが。

は、ここでユーザーの最後の活動を追跡し、時間の間隔で区切られたカウントされますミドルウェアだMiddlewarecustom user models

+0

'process'_responseの最後に' response'オブジェクトを返す必要があります。 django-last-seenはパッケージ化された解決策ですが、私はこの要求に応じていつでも 'LastSeen.object.when'を呼び出す必要があります。もちろん、私はミドルウェアに 'LastSeen.object.when'を入れることができますが、自分のミドルウェアを書くこともできます。 – user2233706

3

I would go for django-last-seen

使用:

from last_seen.model import LastSeen 

seen = LastSeen.object.when(user=user) 
+0

ありがとうございました。私はジャンゴを最後に見てみましょう。 Python Fanboyの答えは十分かもしれませんが、私は "モジュール"に基づいて追跡する必要があります。 – user2233706

+0

本当にいいですね!このパッケージはまだ動作していますか? – ilse2005

+0

このパッケージはdjangoの最新バージョンでは動作しなくなりました。 – Jakobovski

6

(ジャンゴ1.5以降)についてのドキュメントの詳細情報。この間隔を使用すると、データベースへの書き込みを最小限に抑えるという利点とともに、追跡/カウントできる個別の「セッション」が作成されます。

認証ユーザーがリクエストを実行するたびに、最後にアクティビティが見つかった がキャッシュに記録され、新しいタイムスタンプでキャッシュが更新されます。 アクティビティの間隔に少なくとも「間隔」の時間がある場合は、 データベースのタイムスタンプが更新されます。

from datetime import timedelta as td 
from django.utils import timezone 
from django.conf import settings 
from django.db.models.expressions import F  
from <user profile path> import UserProfile 

class LastUserActivityMiddleware(object): 
    KEY = "last-activity" 

    def process_request(self, request): 
     if request.user.is_authenticated(): 
      last_activity = request.session.get(self.KEY) 

      # If key is old enough, update database. 
      too_old_time = timezone.now() - td(seconds=settings.LAST_ACTIVITY_INTERVAL_SECS) 
      if not last_activity or last_activity < too_old_time: 
       UserProfile.objects.filter(user=request.user.pk).update(
         last_login=timezone.now(), 
         login_count=F('login_count') + 1) 

      request.session[self.KEY] = timezone.now() 

     return None 

コメント:

  1. あなたがsettings.LAST_ACTIVITY_INTERVAL_SECSを定義する方法新しいログインであると考えられて非活動の間隔を構成するものを決定。
  2. これは私のUserオブジェクトと1:1の "UserProfile"オブジェクトを更新しますが、あなたが好きなオブジェクトは更新できます。
  3. settings.MIDDLEWARE_CLASSESに必ず入力してください。
  4. このミドルウェアはAPPEND_SLASHが論じられるようrequest.userが使用不能であることが原因となり、process_requestないprocess_responseが他ミドルウェア順序に応じて使用注:Django: WSGIRequest' object has no attribute 'user' on some pages?
+0

私は 'dateutil.parser import parse'を追加して、' last_activityまたはlast_activity

+0

忘れてしまった理由:Djangoセッションでは、明らかにtimezone.now()のようなdatetimeがJSONの直列化可能なデータを必要とするため、代わりにdatetime.isoformat()を使用して文字列として格納し、そのデータを解析してdatetimeに戻す必要がありました。 –

関連する問題