4

私の質問がこれと非常に似ていて、問題を解決しようとする私のアプローチがその質問への回答に基づいている場合はお詫びしますが、これはもう少し複雑で、完全に理解していない Django の一部を対象とする可能性があると思います.


Django 1.5 で記述された CMS システムがあり、ブラウザのように Cookie を使用できない 2 つのデスクトップ アプリケーションからアクセスできるいくつかの API があります。

アプリケーションの 1 つによって API 呼び出しが行われるたびに (3 秒に 1 回)、新しいエントリがdjango_sessionテーブルに追加されることに気付きました。この表とコードをよく見ると、特定の URL へのすべてのエントリに同じsession_data値が与えられていますが、異なるsession_key. これはおそらく、Django が、これらの呼び出しのいずれかが Cookie を使用しないアプリケーションから行われた場合request.session._session_keyNone.

その結果、毎日数千のエントリがdjango_sessionテーブルに作成され、毎日の cron を使用して単純に実行./manage clearsessionsしても、このテーブルからエントリが削除されないため、データベース全体が非常に大きくなり、明らかな利点はありません。set_expiry(1)私もこれらのリクエストを試みましたが、./manage clearsessionsまだそれらを取り除かないことに注意してください。

Django でこの問題を解決するには、SessionMiddleware、AuthenticationMiddleware、MessageMiddleware を使用しているため、3 つの Django ミドルウェアをオーバーライドする必要がありました。

from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.auth.middleware import AuthenticationMiddleware
from django.contrib.messages.middleware import MessageMiddleware

class MySessionMiddleware(SessionMiddleware):
    def process_request(self, request):
        if ignore_these_requests(request):
            return
        super(MySessionMiddleware, self).process_request(request)

    def process_response(self, request, response):
        if ignore_these_requests(request):
            return response
        return super(MySessionMiddleware, self).process_response(request, response)

class MyAuthenticationMiddleware(AuthenticationMiddleware):
    def process_request(self, request):
        if ignore_these_requests(request):
            return
        super(MyAuthenticationMiddleware, self).process_request(request)

class MyMessageMiddleware(MessageMiddleware):
    def process_request(self, request):
        if ignore_these_requests(request):
            return
        super(MyMessageMiddleware, self).process_request(request)

def ignore_these_requests(request):
    if request.POST and request.path.startswith('/api/url1/'):
            return True
    elif request.path.startswith('/api/url2/'):
        return True
    return False

上記は機能しますが、実際にはこれをより複雑にした可能性があり、リクエストごとに4つの追加チェックが行われるため、これは最も効率的なアプローチではないという考えを止めることはできません.

Djangoで上記を行うより良い方法はありますか? どんな提案でも大歓迎です。

4

2 に答える 2

2

汚いハック: 条件付きでセッション オブジェクトを削除します。

1 つのアプローチは、リクエストに応じてセッション オブジェクトを破棄する単一のミドルウェアを含めることです。2 つの理由から、これは少し汚いハックです。

  • Session オブジェクトは最初に作成され、後で削除されます。(非効率的な)
  • その時点ではまだ Session オブジェクトがデータベースに書き込まれていないという事実に依存しています。これは、将来の Django バージョンで変更される可能性があります (可能性は低いですが)。

カスタム ミドルウェアを作成します。

class DiscardSessionForAPIMiddleware(object):

    def process_request(self, request):
        if request.path.startswith("/api/"): # Or any other condition
            del request.session

のタプルのにこれをインストールしてください。django.contrib.sessions.middleware.SessionMiddlewareMIDDLEWARE_CLASSESsettings.py

また、が(デフォルト)settings.SESSION_SAVE_EVERY_REQUESTに設定されていることを確認します。Falseこれにより、データが変更されるまでデータベースへの書き込みが遅延します。


代替案 (未テスト)

  • process_viewカスタム ミドルウェアの代わりに使用process_requestして、リクエスト パスの代わりにビューを確認できるようにします。利点: 状態チェックが優れています。欠点: 他のミドルウェアが既にセッション オブジェクトで何かを行っている可能性があり、このアプローチは失敗します。
  • そこにあるセッション オブジェクトを削除する API ビュー用のカスタム デコレータ (または共有基本クラス) を作成します。利点: これを行う責任は、おそらく最も気に入っている場所であるビュー (API を提供するビュー) にあります。短所: 上記と同じですが、さらに後の段階でセッション オブジェクトを削除します。
于 2013-06-13T14:21:14.913 に答える
0

settings.SESSION_SAVE_EVERY_REQUESTが に設定されていることを確認してくださいFalse。これは、セッションが毎回保存されないようにするのに大いに役立ちます。

また、サーバーに送信される ajax リクエストがある場合は、リクエストに Cookie 情報が含まれていることを確認して、サーバーが各リクエストが別の人物に属していると判断しないようにします。

于 2013-06-13T13:32:13.397 に答える