46

ユーザーがログインしていない場合、サイトのすべてのページにログインフォーム (django.contrib.auth の AuthenticationForm) を表示したいと思います。ユーザーがログインすると、同じページにリダイレクトされます。エラーがある場合は、フォームと同じページにエラーが表示されます。

すべてのテンプレートにフォームを提供するには、コンテキスト プロセッサが必要になると思います。しかし、投稿されたフォームを処理するためにすべてのビューも必要ですか? これは、ミドルウェアを作成する必要があるということですか? 私は少し迷っています。

これを行うための受け入れられた方法はありますか?

4

4 に答える 4

34

わかりました、私は最終的にこれを行う方法を見つけましたが、より良い方法があると確信しています. LoginFormMiddleware という新しいミドルウェア クラスを作成しました。process_request メソッドでは、認証ログイン ビューとほぼ同じ方法でフォームを処理します。

class LoginFormMiddleware(object):

    def process_request(self, request):

        # if the top login form has been posted
        if request.method == 'POST' and 'is_top_login_form' in request.POST:

            # validate the form
            form = AuthenticationForm(data=request.POST)
            if form.is_valid():

                # log the user in
                from django.contrib.auth import login
                login(request, form.get_user())

                # if this is the logout page, then redirect to /
                # so we don't get logged out just after logging in
                if '/account/logout/' in request.get_full_path():
                    return HttpResponseRedirect('/')

        else:
            form = AuthenticationForm(request)

        # attach the form to the request so it can be accessed within the templates
        request.login_form = form

リクエスト コンテキスト プロセッサがインストールされている場合は、次の方法でフォームにアクセスできます。

{{ request.login_form }}

非表示フィールド「is_top_login_form」がフォームに追加されていることに注意してください。これにより、ページに投稿された他のフォームと区別できるようになりました。また、フォームアクションは「.」です。認証ログインビューの代わりに。

于 2010-08-11T13:08:37.013 に答える
26

django.contrib.auth を使用すると、次のようにフォーム コードをベース テンプレートに入れることができます。

<form method="post" action="{% url auth_login %}">
    {% csrf_token %}
    <p><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="30" /></p>
    <p><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></p>

    <input type="submit" value="Log in" />
    <input type="hidden" name="next" value="" />
</form>

あなたがする必要があるのは、代わりに次の値を変更することです:

<input type="hidden" name="next" value="" />

次のようになります。

<input type="hidden" name="next" value="{{ request.get_full_path }}" />

リクエストオブジェクトにアクセスするには、必ず含めてください

'django.core.context_processors.request'

テンプレート コンテキスト プロセッサで。この方法では、Django 組み込みビューを使用しているため、ログイン用のコンテキスト プロセッサを作成する必要はありません。

于 2010-06-26T17:44:39.120 に答える
6

最も簡単な方法は、おそらく次のようにフォームをベーステンプレートに手動で配置することです。

{% if user.is_authenticated %}
    <form action="{% url login %}" method="POST">{% csrf_token %}
        <input id="username-field" name="username" type="text" />
        <input id="password-field" name="password" type="password" />
        <button type="submit">Login</button>
    </form>
{% else %}
    {# display something else here... #}
{% endif %}

次に、「login」という名前のURLに接続されたビューを記述して、通常どおりにフォームを処理します(上記のフォームに一致するフォームオブジェクトを使用)。ビューをリダイレクトしrequest.META['HTTP_REFERER']て、送信したページと同じページに表示します。

このアプローチにより、ミドルウェアや、コンテキストを通じてすべてのテンプレートでフォームを使用できるようにする必要がなくなります。

更新:このアプローチにはいくつかの問題があります。もう少し考える必要があります。うまくいけば、少なくともそれはあなたを正しい方向に向かわせるでしょう。

于 2010-04-29T02:22:31.240 に答える
2

asciitaxi の回答に基づいて、これらのミドルウェア クラスを使用してログインおよびログアウトします。

class LoginFormMiddleware(object):
    def process_request(self, request):
        from django.contrib.auth.forms import AuthenticationForm
        if request.method == 'POST' and request.POST.has_key('base-account') and request.POST['base-account'] == 'Login':
            form = AuthenticationForm(data=request.POST, prefix="login")
            if form.is_valid():
                from django.contrib.auth import login
                login(request, form.get_user())
            request.method = 'GET'
        else:
            form = AuthenticationForm(request, prefix="login")
        request.login_form = form

class LogoutFormMiddleware(object):
    def process_request(self, request):
        if request.method == 'POST' and request.POST.has_key('base-account') and request.POST['base-account'] == 'Logout':
            from django.contrib.auth import logout
            logout(request)
            request.method = 'GET'

私の基本テンプレートのこれ:

{% if not request.user.is_authenticated %}
    <form action="" method="post">
        {% csrf_token %}
        <p id="login">
            {{ request.login_form.non_field_errors }}
            {% for field in request.login_form %}
                {{ field.errors }}
                {{ field.label_tag}}: {{ field }}
            {% endfor %}
            <input type="submit" name="base-account" value="Login" />
        </p>
    </form>
{% else %}
    <form action="" method="post">
        {% csrf_token %}
        <p id="logout">Logged in as <b>{{ request.user.username }}</b>.
            <input type="submit" name="base-account" value="Logout" />
        </p>
    </form>
{% endif %}

備考:

  • request.method = 'GET' 行は、他のフォームを持つサイトに必要です。少し悪いように見えますが、うまく機能します。
  • これはすべてのページに表示されるため、ログアウトの特別なケースはもう必要ありません。別のログアウト ページは必要ないからです。
  • 有効かどうかを確認する前に、ログイン/ログアウトフォームを区別する必要があります(したがって、AuthenticationFormクラスを呼び出します。そうしないと、より多くのフォームを含むページになるとエラーが発生します。したがって、送信ボタンの値を使用して選択します関連するケース
于 2013-03-13T23:41:36.377 に答える