取り急ぎ Django でログイン機能を作った方法(クラスベースビュー)

とりあえず Django のクラスベースビューでログイン機能を追加した時の内容をまとめます。

  1. views.py で LoginRequiredMixin の継承
  2. forms.py でログインフォームを作成
  3. views.py で ログインビューの作成
  4. urls.py でパスと view の紐付け
  5. ログイン用テンプレートの作成
  6. ログインの動きのまとめ
  7. ログアウトページの作成

views.py で LoginRequiredMixin の継承

非ログインユーザーに表示させたくない View 全てで LoginRequiredMixin を継承します。

複数のクラスを継承している場合、下記の例の様に必ず一番目に記述します。

# views.py
class ClassList(LoginRequiredMixin, generic.ListView):
    model = ClassMaster
    template_name = 'class_list.html'

class ClubList(LoginRequiredMixin, generic.ListView):
    model = ClubMaster
    template_name = 'club_list.html'

非ログインユーザーが LoginRequiredMixin を継承したビューに当たった場合、デフォルトで accounts/login/ にリダイレクトされますが、下記の様に settings.py に明示的に LOGIN_URL としてリダイレクト先を設定することも可能です。

# settings.py
LOGIN_URL = 'http://ドメイン名/login' # 一例です。

上記いずれかのパスでログインビューを表示する様、後ほど設定します。

また、リダイレクトされる際、元々アクセスしようとしていたパスを next パラメータとして URL に保持した状態で飛んでいきます。これも後ほどログイン後のリダイレクトに利用します。

forms.py でログインフォームを作成

AuthenticationForm クラスを継承してフォームを作成します。とりあえず username と password のみ認証対象とします。

# forms.py

from django.contrib.auth.models import User
from django.contrib.auth.forms import AuthenticationForm

class LoginForm(AuthenticationForm):
    class Meta:
        model = User
        fields = ['username', 'password']

views.py で ログインビューの作成

ログイン用のビューは LoginView クラスを継承して作成します。

ログインフォームの表示と、ユーザーから submit されたログイン情報の認証、そしてユーザーが元々アクセスしようとしていたページへのリダイレクト等を担ってくれます。

# views.py

from django.contrib.auth.views import LoginView

class MyLoginView(LoginView):
    form_class = LoginForm

template_name を指定しなくてもデフォルトで registration/login.html になっているので上記の例では明記していませんが、他の view 同様 「template_name = 'login.html'」の様に設定することも可能です。

また、LoginView クラスは POST 時に next URL を渡すとログイン後その URL にリダイレクトしてくれます

"If called via POST with user submitted credentials, it tries to log the user in. If login is successful, the view redirects to the URL specified in next. If next isn’t provided, it redirects to settings.LOGIN_REDIRECT_URL (which defaults to /accounts/profile/). If login isn’t successful, it redisplays the login form."

後ほどテンプレートを作成する際に form からの POST 時に next 渡す様設定します。

urls.py でパスと view の紐付け

アプリケーションレベルの urls.py にログインページのパスとログイン用 view の紐付けを記載します。

# urls.py

from django.urls import path
from . import views

app_name = 'sample_app'
urlpatterns = [
    #〜省略〜
    path('accounts/login/', views.MyLoginView.as_view(), name="login"),
    #〜省略〜
]

ログイン用テンプレートの作成

作成したログインフォームを表示するテンプレートを作ります。

Form 部分の記述は下記の様な感じ。

<!--login.html-->
 
<form action="{% url 'sample_app:login' %}" method="post">
    {% csrf_token %}
        {{ form.as_p }}
        <p><input type="hidden" name="next" value="{{next}}"></p>
        <p><input type="submit" value="ログイン"></p>
    </form>

いくつかポイントがあります。

  • ログインフォーム自身に対して POST する。
  • input の一つとして、リダイレクトされた時に持ってきた next URL を裏で取っておく(type="hidden" で非表示にしています)。

こうしておくことで、ログイン成功時に LoginView がリダイレクトしてくれます。

ログインの動きのまとめ

というわけで、ログイン部分を一通り作りました。

非ログインユーザーがアクセスした場合、下記の様な流れになります。

  1. 非ログインユーザーがページへアクセスしようとする。
  2. LoginRequiredMixin によって、アクセスしようとしていたページのパスを next に保持したままログインページ(LoginView)へリダイレクトされる。
  3. リダイレクト先でのログインフォームでユーザー名とパスワードを Submit する際、next も一緒に LoginView に対して POST する。
  4. 認証に問題がなければ、ログインされ、next のパスにリダイレクトされる。

ログアウトページの作成

一応ログアウト部分もやっつけで書いておきます。

サイトのヘッダー部分など、どこかしらにログアウト用リンクを作って、ログアウトビューとつなげる感じです。

views.py

LogoutView クラスを継承したビューを作成し、任意の template_name を指定します。

# views.py

class MyLogoutView(LogoutView):
    template_name = 'テンプレート名.html'

urls.py

ログアウト用のパスとログアウト用の view を繋げるだけです。

# urls.py

from django.urls import path
from . import views

app_name = 'sample_app'
urlpatterns = [
    #〜省略〜
    path('accounts/login/', views.MyLoginView.as_view(), name="login"),
    path('accounts/logout/', views.MyLogoutView.as_view(), name="logout"),
    #〜省略〜
]

テンプレート

テンプレートでは、任意の場所にハイパーリンクを置いてログアウト用 URL に飛ぶ様にすれば大丈夫です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です