ユーザーがログインしていない場合、ログインフォーム(Django.contrib.authのAuthenticationForm)をサイトのすべてのページに表示したいのですが、ユーザーがログインすると、同じページにリダイレクトされます。エラーがある場合、エラーはフォームと同じページに表示されます。
すべてのテンプレートにフォームを提供するには、コンテキストプロセッサが必要だと思います。しかし、投稿されたフォームを処理するためにすべてのビューも必要ですか?これは、ミドルウェアを作成する必要があることを意味しますか?少し迷ってしまいました。
これを行うための受け入れられた方法はありますか?
わかりました。やっとこれを行う方法を見つけましたが、もっと良い方法があると確信しています。 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」がフォームに追加されたことで、ページに投稿された他のフォームと区別できることに注意してください。また、フォームアクションは「。」です。 auth loginビューの代わりに。
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組み込みビューを使用しているため、この方法では、ログイン用のコンテキストプロセッサを記述する必要はありません。
最も簡単な方法は、おそらく次のようにフォームを手動でベーステンプレートに配置することです。
{% 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 %}
次に、「ログイン」という名前のURLに接続されたビューを記述して、通常どおりにフォームを処理します(上記のフォームに一致するフォームオブジェクトを使用)。送信したページと同じページに表示するには、ビューをrequest.META['HTTP_REFERER']
にリダイレクトします。
このアプローチにより、ミドルウェアや、コンテキストを介してすべてのテンプレートでフォームを使用できるようにする必要がなくなります。
更新:このアプローチにはいくつかの問題があります。もう少し考える必要があります。うまくいけば、少なくともあなたは正しい方向に行くことができます。
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 %}
備考: