Django2 でユーザー認証(ログイン認証)を実装するチュートリアル -2- サインアップとログイン・ログアウト

Django2 でユーザー認証(ログイン認証)を実装するチュートリアル -1- 環境構築とアプリ雛形の作成 の続きです。今回は前回作った(ダミーの)ブログ・アプリにユーザー登録(サインアップ)ユーザー認証(ログイン・ログアウト)を実装していきます。

認証機能のインストールと設定

Django2 はユーザー認証機能を標準搭載しています。設定作業も不要です。デフォルトで認証機能が有効化されているので、通常は何もする必要はありません。

既存のDjangoプロジェクトを引き継ぐ場合や認証が機能しない場合にはインストール要件を確認してみましょう。

 

認証機能の使い方

Django公式ドキュメント「Djangoの認証システムを使用する」はページの半分が英語の原文ままなのと情報量が多すぎて、はじめて使う場合にはわかりにくいかと思います。

ユーザー認証をはじめて実装作業するにあたって大切なのは Authentication Views というセクションです。※2018年1月時点では翻訳されてません。

Django provides several views that you can use for handling login, logout, and password management. These make use of the stock auth forms but you can pass in your own forms as well.

Django provides no default template for the authentication views. You should create your own templates for the views you want to use. The template context is documented in each view, see All authentication views.

https://docs.djangoproject.com/ja/2.0/topics/auth/default/#module-django.contrib.auth.views より引用

重要なポイントは以下です。

  • Django はログイン、ログアウト、パスワード管理に関するいくつかのビューを提供している
  • Django は認証ビューに対するテンプレートは提供していないので、各自で作成する必要がある

ビュー(ロジック)は提供するけど、テンプレートは各自で作ってね!」とのことです。

Django が提供する認証関連のビュー

「Django provides several views」とのことですが、具体的には以下を提供しています。

  • ログイン
  • ログアウト
  • パスワード変更
  • パスワード・リセット(パスワードを忘れた方はこちら)

Django標準搭載の認証機能を使えば、これらのビュー(ロジック)の実装をやらなくて良いのです!WEBアプリケーション・フレームワークさまさまですね。

なお、対応するURLパターンもカッチリ決められています。

ユーザー登録(サインアップ)はない!

1点だけとても重要なことがあります。ユーザー登録(サインアップ)に関するビューは提供されないので、開発者が作る必要があります。

ログイン、ログアウト、パスワード変更、パスワードリセットは入力項目が固定されています。一方、ユーザー登録は名前とメールアドレスだけのウェブサイト、住所・性別・年齢・生年月日も必要なウェブサイト…と入力項目は様々です。そのため意図的に標準機能として提供していないのでしょう。

このチュートリアルのURL

手を動かす前にURL設計を確認しましょう。このチュートリアルではユーザー登録とユーザー認証のURLを下記として進めていきます。

ページ・画面 URL例
サインアップ /accounts/signup/
ログイン /accounts/login/
ログアウト /accounts/logout/

では、手を動かしていきましょう。

ログイン・ログアウトの実装

ログイン・ログアウトの処理は決まった流れに沿うだけです。

  1. LOGIN_REDIRECT_URL の設定(オプション)
  2. プロジェクトレベルURL設定
  3. テンプレートの作成

1. LOGIN_REDIRECT_URL の設定

ログイン後にリダイレクトされるページのURLを設定するため、プロジェクトの設定ファイル myblog/settings.py に下記を追加します。

なお、この設定はオプションです。もし設定しない場合(デフォルト)は /accounts/profile/ にリダイレクトされます。

2. プロジェクトレベルURL設定

myblog/myblog/urls.py に path(‘accounts/’, include(‘django.contrib.auth.urls’)) を追加します。これにより認証関連のビューが有効化されます。ログイン・ログアウトに関するビューの実装はこれだけで完了です。

 

3. テンプレートの作成

Django は認証ビューに対応するテンプレートは提供しないため、開発者が作成する必要があるのでしたね。レイアウトファイル(ベーステンプレート)の作成、ログインとログアウトに関するテンプレートを作っていきましょう。

レイアウトファイルの作成

まずヘッダー・フッター等の共通箇所をレイアウトファイル(ベーステンプレート)として切り出します。

Django はテンプレートファイルについてガチガチの規約はありません。自由度が高く、どこにでも設置することができます。Django2 入門チュートリアル – CRUDの基本を簡単なサンプルで学ぶ – 4 – 汎用クラスベースビューによるCRUDの実装 ではアプリケーション下に templates ディレクトリを設置しましたが、このチュートリアルではプロジェクト直下に templates ディレクトリを設置していきましょう。

プロジェクト(ウェブサイト)全体で共通するレイアウトや画面のテンプレートはプロジェクト下の templates に設置。プロジェクト内の各アプリケーション固有のテンプレートについてはアプリケーション下の templates に設置するのが定番パターンです。

まずプロジェクト直下に templates というディレクトリを新規作成します。

 

開発者が自由に作っただけなので、Django はこのことを知りません。Django に「どこどこに templates ディレクトリを設置したよ!」ということを伝える必要があります。

プロジェクトの設定ファイル myblog/myblog/settings.py を編集し、作成した templatesディレクトリのパスをTEMPLATES  DIRS に追加します。これで Django は先ほど設置した templates ディレクトリを認識できるようになります。

‘./templates’ や ‘templates’ としても認識されますが、厳密に os.path.join(BASE_DIR, ‘templates’) と指定する方が良いでしょう。

続いてレイアウトファイル(ベーステンプレート) base.html を作成します。myblog/templates/base.html を新規作成しましょう。base.html は単なるテンプレートファイルなので難しいことはありません。ソースコードをここに貼り付けると冗長なので、Githubで確認ください。Githubでbase.html のソースを確認

 

ログイン・ログアウトのテンプレート作成

ベーステンプレートができたところで、「ログイン画面」と「ログアウト画面(ログアウトした直後に表示する画面)」のテンプレートを作成していきましょう。

テンプレートのパス(ディレクトリとファイル名)はあらかじめ決められています。

ログイン画面: templates/registration/login.html
ログアウト画面: templates/registration/logged_out.html

というパスにファイルを作成します。

※突然 registration というディレクトリが出てきますが、これは単に Django の認証機能がそこに設置するよう決めてるからです。

ファイルの中身(ソースコード)についても、雛形に沿うだけです。公式ドキュメントにサンプルがあるので、下記ページを確認しておきましょう。
https://docs.djangoproject.com/ja/2.0/topics/auth/default/#all-authentication-views

login.html の例

 

ログイン画面テンプレートの核は「ユーザー名」と「パスワード」の入力フォームだけで、あとは入力に応じてエラーメッセージを出す程度です。

logged_out.html の方ですが、こちらは「ログアウトしました」と表示するだけでフォームさえ必要ありません。デモサイトのソースコードはGithubで確認ください。login.html と logged_out.html を確認

以上でログイン・ログアウトの実装が完了です。

ブラックボックス??

ビューを作る必要もなく、テンプレートもパスや雛形が決まっていたりと、「ブラックボックス」のように感じるかもしれませんが、ログイン・ログアウトの機能はどのウェブアプリケーションでも基本的に同じです。開発者の労力を最小限に抑えるよう、Djangoが共通処理をすべて実装してくれているためです。

Djangoは単なるPythonスクリプトです。ブラックボックスが嫌な場合はDjango本体のソースコードを確認しましょう。

なお、Djangoの認証機能は一般的なケースを想定しています。ソーシャルログインなど特別なことをしたければ各自で拡張・実装する必要があります。

Django の認証システムは一般的であることを狙いとしており、ウェブ上の認証システムで見られるようないくつかの機能を有していません。これらに共通する問題の解決策は、サードパーティのパッケージにて実装されます。

パスワード強度のチェック
ログイン試行数の制限
サードパーティに対する認証 (OAuthなど)

https://docs.djangoproject.com/ja/2.0/topics/auth/ より引用

 

サインアップの実装

サインアップ(ユーザー登録)については、開発者が実装する必要があります。アプリケーション accounts を作成してサインアップを実装していきましょう。

アプリケーションの作成と有効化

仮想環境 myenv でアプリケーション accounts を作成します。※仮想環境myenvについて不明な場合は前回記事「環境構築とアプリ雛形の作成」を参照ください。

 

続いてプロジェクトの設定ファイル myblog/myblog/settings.py に accounts アプリを追加します。

 

モデルの追加

あらたにモデルを追加する必要はありません。myblog/accounts/models.py はそのままの状態でOKです。

 

URL設定(URLConf)

Django2.0 のURL設定は「アプリレベルのURL設定」と「プロジェクトレベルのURL設定」の2段階でしたね。順に行なっていきます。

myblog/accounts/urls.py を新規作成しましょう。

 

myblog/myblog/urls.py にaccounts に関する設定を追加します。

 

ビューの作成

myblog/accounts/views.py を編集します。サインアップ(ユーザー登録)のビューは開発者が実装する必要があるものの、一からスクラッチで作る必要はありません。新しいユーザを作成するための UserCreationForm というクラスをDjangoは提供しています。これと汎用クラスベースビューCreateView を使えば数行で実装することができます。

 

テンプレートの作成

まず myblog/accounts/templates/accounts/ というディレクトリを作りましょう。templates の下にさらに accounts ディレクトリを追加するのは「テンプレートの名前空間」という意味を持ちます。

その後 signup.html (myblog/accounts/templates/accounts/signup.html)を新規作成します。ユーザー登録だからといって特別なことはなく、汎用クラスベースビューによる典型的なテンプレートです。

 

以上でサインアップの実装は完了です。

ログイン制限の実装方法

ログイン・ログアウト・サインアップが一通り揃いましたが、ログインしていないユーザーにアクセスできないようにする必要があります。様々な実装方法がありますが、ここでは最も簡単かつよく使われる方法を紹介いたします。

login_required デコレータ

views.py に定義したビュー関数の直前に @login_required と追記すれば(するだけで)、ログインしたユーザーのみに閲覧制限できます。

ビュー関数の前につける @login_required のことを login_required デコレータと呼びます。login_required デコレータは下記の処理を行います。

もしユーザがログインしていなければ、settings.LOGIN_URL にリダイレクトし、クエリ文字列に現在の絶対パスを渡します。リダイレクト先の例: /accounts/login/?next=/polls/3/
もしユーザがログインしていれば、通常通りビューを処理します。ビューのコードの中ではユーザがログインしているかを意識しなくて良いのです。

https://docs.djangoproject.com/ja/2.0/topics/auth/default/#the-login-required-decorator より引用

 

LoginRequiredMixin

@login_required は関数の場合のみ有効でクラスには効きません。クラスベースビューの場合には LoginRequiredMixin を使用します。下記のように LoginRequiredMixin を継承すれば、ログインしたユーザーのみに閲覧制限できます。

 

Django2.0 によるサインアップとログイン・ログアウトについては以上です。次の記事ではブログアプリを仕上げていきます。

3 Comments

cozy

とても纏まっていて素晴らしい記事です。ありがとうございます。
一つ抜けがありまして、login.htmlの{% endblock%}がないです。よろしくお願いします。

返信する

コメントを残す

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