3

支払いゲートウェイをセットアップしており、セッションを使用してページ リクエスト間でデータを保存しています。以下のクラスは、情報を編成してセッションに保存するために使用されます。

class Gateway:
  def __init__(self, session_key=None, session_name="FOO"):
    # Store session ID and name
    self.session_key    = session_key
    self.session_name   = session_name

    # Get the session
    session = SessionStore(session_key=self.session_key)

    try :
      data = session[self.session_name]
    except :
      data  = {user_id:None, checked_in:False }

    self.__dict__.update(data)

  def save(self) :
    session = SessionStore(session_key=self.session_key)
    session[self.session_name] = deepcopy(self.__dict__)
      try :
        del session['session_key']
        del session['session_name']
      except :
        pass
    session.save()

このビューは、ユーザーがログインしているかどうかを確認します。ログインしている場合は、リダイレクトされます。そうでない場合は、ゲストとしてログインまたはチェックインするよう求められます。

def check_in(request):
  gateway = Gateway(session_key=request.session.session_key)

  if request.user.is_authenticated():
    gateway.user_id = request.user.id
    gateway.checked_in = True
    gateway.save()

    return redirect('next_step')
  else:
    login_form = FormLogin()
    if request.POST:
      data = request.POST.copy()
      if 'login' in data:
        login_form = FormLogin(data)
        if login_form.is_valid():
          user = login(request, login_form)
            if user:
              gateway.user_id = user.id
              gateway.checked_in = True
              gateway.save()
              return redirect('next_step')
        elif 'guest' in data:
          gateway.checked_in = True
          gateway.save()
          return redirect('next_step')
    return render(
      request,
      'shop/login.html',
      {
        'login_form':login_form,
      }
    )

次のビューは、「checked_in」変数をチェックします。これは、ユーザーがログイン/チェックイン プロセスをスキップしないようにするためです。(補足として、関数「login(request, login_form)」は、他のコンテキストで完全に機能する関数であり、成功した場合は User を返し、それ以外の場合は None を返します)

def next_step(request):
  gateway = Gateway(session_key=request.session.session_key)

  if not gateway.checked_in:#edited 
    messages.info(request, _(u'You must specify login first.'))
    return redirect('check_in')
  else:
    #do the next step

問題は次のとおりです。

ユーザーが認証されている場合でも、「checked_in」変数はまだ false であり、ビューがループします。変数を設定して保存するたびに、新しいセッション ID を持つ新しいセッションが作成されます。django ドキュメントには、セッションの変更に関する説明がありますが、新しいセッションが作成される理由やセッション キーが変更される理由がわかりません。

編集: データベース バックエンドを使用しています。

4

3 に答える 3

1

このバグ/問題を複製しました:

URL ルール

url(r'^test/', 'shop.views.catalog.test', name="test")

ビュー機能

def test(request) :
    key1 = request.session.session_key
    request.session['test'] = 'test'
    key2 = request.session.session_key

    raise Exception("%s : %s === %s" % (key1, key2, request.session['test']))
  1. 127.0.0.1 の Cookie をクリアする
  2. 127.0.0.1:8000/test/ に移動します
    • /test/ 4793f2453758d7021a43a348a0f40a83 での例外: 8568f729991e740395179c56cd37cf18 === テスト
  3. ページを更新する (Cookie をクリアしない)
    • /test/ 8568f729991e740395179c56cd37cf18 での例外: 8568f729991e740395179c56cd37cf18 === テスト

そのため、セッションが初めて変更されるまで、別のセッション キーを使用しています...予期しない動作が発生します。その理由も気になります。

于 2012-06-26T15:37:14.113 に答える
1

アクセスまたは変更されていない場合、Djangoはデータベースへのセッションを永続化しないため、SessionStoreの初期化に使用しているsession_keyは実際にはデータベースエントリによってサポートされていないと思います.

この場合: SessionStore を保存すると、新しい session_key が自動的に割り当てられ [1] (既存のキーが DB に存在せず、セッション固定を回避したいため [2])、DB に保存されますが、 SessionStore は request.session (未変更のまま) から独立しているため、クライアントにはこの新しい session_key が割り当てられません。

[1] https://github.com/django/django/blob/master/django/contrib/sessions/backends/db.py#L22

[2] https://groups.google.com/forum/?fromgroups#!topic/django-users/8b_6oTaXv7Q

この仮説をテストするための簡単な修正は、request.session['kate'] = 'bob' を設定してから Gateway クラスを初期化することです。これにより、request.session が強制的に永続化されます。セッションへのアクセスが必要なメソッドが request.session を引数として受け取るように、Gateway クラスをリファクタリングしたい場合があります。

于 2012-06-27T00:08:46.580 に答える