このページでは、Django での「ログイン機能」の実現方法について解説していきたいと思います!
皆さんも Twitter や Instagram を通じてご存知の通り、ウェブアプリにはログイン機能を持ち、ログインしたユーザーに応じた動作・表示を実現するものが多く存在します。
そういったアプリを開発していけるよう、このページでは Django で開発するウェブアプリに「ログイン機能」を持たせるために必要な実装について解説していきたいと思います。
正直いうと、ログイン機能を実現する際の View に関しては、Django に標準で用意されているクラスを継承しながらクラスベースで作成した方が簡単だと思います。ですが、今回はあえて、関数ベースの View でログイン機能を実現していきたいと思います。
関数を自作するので手間はかかりますが、その分 Django においてログインがどのように実現されているかを理解しやすくなると思います。
Contents
ログイン機能を実現するために必要なこと
まずは、ログイン機能を実現するために必要となる処理や動作の全体像をまとめておきたいと思います。
最初に箇条書きで列挙しておくと、ウェブアプリにログイン機能を持たせるためには、下記のような処理や動作を実現していく必要があります。
- ユーザーアカウントの登録
- ログイン
- ログイン後のリダイレクト
- 未ログインユーザーからのアクセス禁止
- ログインユーザーに応じたページ表示
- ログアウト
実際にログインを行うのは2つ目の項目の「ログイン」となりますが、これだけ実現してもウェブアプリにログイン機能を持たせる意味があまりないです。例えばログインしなくてもウェブアプリが利用できたりしてしまいます。
意味のある「ログイン」として機能させるためには、上記の6つくらいの処理や動作を実現した方が良いです。
ここからは、上記で挙げた処理について1つ1つ簡単に説明を行なっていきます。ちょっと実現が難しそうに感じることもあるかもしれませんが、これらは Django に用意されたクラスや関数を利用すれば簡単に実現することが出来ます!
ユーザーアカウントの登録
まず、ログイン機能を実現するためには、ユーザーアカウントの登録を行えるようにする必要があります。
ユーザーアカウントは管理画面から作成することも可能ですが、この場合は管理者権限を持つユーザーしかユーザーアカウント作成ができません。
今回は管理者権限を持つユーザーだけでなく、ウェブアプリの利用者自身がユーザーアカウントを作成できるように、下の図のようなユーザーアカウント登録フォームからユーザーアカウントを登録できるようにしていきたいと思います。
これを実現するためには、上の図のような登録フォームを表示できるようにすることと、フォームに入力された情報が送信されてきた際に、その情報をデータベースのユーザー管理テーブルに保存するような処理が必要になります。
そして、このデータベースへの保存により、ユーザーアカウントの登録が行われることになります。
で、Django の場合、データベースのテーブルは Model 毎に作成されることになります。つまり、ユーザー管理テーブルを作成するための Model が必要ということになります。
ただ、このページでは、この Model として Django に標準で用意されている User
を利用していきたいと思います。
実は Django 公式では User
をそのまま利用することは非推奨されています。ですが、ログイン機能の実現の流れを理解することだけ考えると、そのまま User
を利用したが方が分かりやすと思います。そのため、今回は User
をそのまま利用させていただきます。
実際にウェブアプリを公開する際などは自身でユーザーを管理する Model を用意する必要があります。この Model の作り方については下記ページで解説していますので、本格的なログインを実現したい際には是非参考にしてください。
【Django】カスタムユーザー(独自のユーザー)の作り方【AbstractUser編】 【Django】カスタムユーザー(独自のユーザー)の作り方【AbstractBaseUser編】スポンサーリンク
ログイン
さらに、登録されたユーザーアカウントでログインを行えるようにしていく必要があります。
これは、例えば下の図のようにログインフォームを表示し、
さらにフォームから送信されてきたユーザー名やパスワード等の情報から、登録されたユーザーアカウントであるかどうかの認証を行うような処理が必要になります。
要は、フォームから送信されてきたユーザー名がユーザ管理テーブルに保存されているかどうか、さらに送信されてきたパスワードが正しいのかどうかを確認する必要があります。
そして認証が OK の場合のみ、フォームを送信してきたユーザーがログインできるようにする必要があります。
ちょっと難しそうではありますが、認証・ログインともに Django に用意されているクラスや関数を利用することで簡単に実現することが出来ます。
ログイン後のリダイレクト
また、多くのウェブアプリでは、ユーザーがログインできた際にはログインフォームが再び表示されるのではなく、例えばユーザーのホームのページのような他のページへのリダイレクト(自動的に転送)が行われるようになっています。
このリダイレクトはログインには必須ではないですが、ユーザーのアプリの使いやすさを考えると、こういったログイン後のリダイレクトも実現しておいた方が良いです。
未ログインユーザーのアクセス禁止
さて、このページではログイン機能を実現しようとしているのですが、そもそもユーザーにわざわざログインをさせる目的は何でしょうか?
ウェブアプリによって目的は異なると思いますが、下記のような目的が挙げられると思います(後者に関しては次の ログインユーザーに応じたページ表示 で解説します)。
- ログインユーザーしかウェブアプリを使用できないようにする
- ユーザーを識別してユーザーに応じた処理を行う(ユーザーに応じた情報を表示する)
前者を実現するためには、未ログインのユーザーが「ログイン中でないと見れないページ」にアクセスしてきた時にログインページにリダイレクトを行うような処理が必要になります(エラーを表示するなどの手段で実現することも可能です)。
ちょっと面倒そうですが、これは login_required
というデコレータを利用するだけで簡単に実現することが出来ます。
スポンサーリンク
ログインユーザーに応じたページ表示
また、先ほどログイン機能を設けることの目的の2つ目として挙げたように、ログイン機能を設け、ユーザーに応じて表示する情報を変化させるようなことも可能です。
例えばショッピングアプリで考えると、購入履歴のページは当然ログイン中のユーザーに応じて変化させる必要があります。こういったログインユーザーに応じたページ表示もログイン機能を持つウェブアプリに必要になる処理となります。
こういったユーザーの情報はユーザーを管理する Model、もしくは、その Model とリレーションが構築されている Model から取得することが出来ます。
今回はユーザーを管理する Model としては Django に標準で用意されている User
を使用しますので、User
に用意されている情報しかページに表示することが出来ません。しかし、ユーザーを管理する Model を自作して必要なフィールドを持たせるようにしてやれば、前述のような購入履歴などの様々な情報を表示することができるようになります。
スポンサーリンク
ログアウト
また、ログインしたユーザーがいつでもログアウトを行えるようにログアウト機能も備えておいた方がセキュリティ的に良いと思います。
ログアウト機能に関しても、Django に用意されている logout
関数の利用によって簡単に実現することが可能です。
ログイン機能を持つウェブアプリの作り方
大体ログイン機能を持つウェブアプリを実現するために必要な処理や動作については理解していただけたのではないかと思いますので、ここからは、具体的にソースコード等も参照しながらログイン機能を持つウェブアプリの作り方について解説していきたいと思います。
スポンサーリンク
事前準備(プロジェクトやアプリの作成など)
以降ではソースコードも変更しながら実際にログイン機能を実現していきたいと思いますので、まずは事前準備としてプロジェクトやアプリの作成・urls.py
の設定等を行なってアプリの大枠だけ作成していきたいと思います。この辺りは通常のウェブアプリを開発するときと同様にして作成して問題ありません。
今回は、プロジェクト名は login_project
・アプリ名は login_app
として解説を行なっていきます。
プロジェクトの作成
まずは通常通り、プロジェクトを下記コマンドで作成していきましょう!
% django-admin startproject login_project
以降では、ファイルのパスは上記で作成した「login_project
フォルダからの相対パス」で記述していきますので、その点にご注意してください。
また、django-admin
実行時にエラーが出る方は下記ページを参考にしていただければと思います。
アプリの作成
先ほど実行したコマンドにより login_project
フォルダが作成されますので、次は login_project
フォルダの中で下記コマンドを実行してアプリを作成します。今回作成するアプリの名称は、前述の通り login_app
とします。
% python manage.py startapp login_app
アプリの登録
続いて、login_project/settings.py
に下記の1行を追記してプロジェクトにアプリの登録を行います。
# Application definition
INSTALLED_APPS = [
'login_app', # 追記
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
View の大枠の作成
次は、login_app/views.py
を下記のように変更して View の大枠を作成しておきます。
現状では各関数は何もしない状態になっていますが、以降で views.py
を作り込んでいくことでログイン機能を実現していきます。
from django.shortcuts import render
def signup_view(request):
pass
def login_view(request):
pass
def logout_view(request):
pass
def user_view(request):
pass
def other_view(request):
pass
上記の login_app/views.py
の各関数は、次のような役割を持つ関数となるように今後の解説の中で実装を行なっていきます。
signup_view
:ユーザーアカウントの登録login_view
:ユーザーのログインlogout_view
:ユーザーのログアウトuser_view
:ログインユーザーの情報の表示other_view
:他のユーザーの情報の表示
View と URL の関連付け
さらに、先ほど作成した View の関数と URL の関連付けを login_project/urls.py
と login_app/urls.py
とで行なっていきます。
まずは、login_project/urls.py
を下記のように変更し、login_app/
から始まる URL が指定された際に login_app/urls.py
を参照するようにします。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('login_app/', include('login_app.urls'))
]
さらに、login_app/urls.py
を下記のように新規作成します。
from . import views
from django.urls import path
urlpatterns = [
path('signup/', views.signup_view, name='signup'),
path('login/', views.login_view, name='login'),
path('logout/', views.logout_view, name='logout'),
path('user/', views.user_view, name='user'),
path('other/', views.other_view, name='other'),
]
これにより、例えば http://localhost:8000/login_app/signup/
の URL にアクセスがあった際に(URL へのリクエストがあった際に)、login_app/views.py
の signup_view
関数が実行されるといった具合に、各 URL と View の関数が関連付けられることになります。
マイグレーション
最後に、startproject
実行時に作成された login_project
フォルダの中で下記のコマンドを実行してマイグレーションを行います(models.py
を変更していないため、今回は makemigrations
は不要です)。
% python manage.py migrate
models.py
は変更していませんが、Django では認証用のモデルとして User
がデフォルトで利用されるようになっているため、models.py
にモデルを定義しなくても上記コマンドを実行すればデータベースに User
用のテーブル(auth_user
)が作成される事になります。
ユーザーアカウントを登録した場合には、この auth_user
にユーザーの情報をレコードとして保存することになりますし、ログインを行う際には、ログインフォームに入力されたユーザー名のレコードが auth_user
に保存されているか、さらに入力されたパスワードがそのレコードのパスワードと同じであるかどうかの確認が行われることになります。
ちなみに、上の図は VSCode のプラグインである SQLite Viewer
を利用してテーブルの中身を表示した結果となります(まだ中身は空ですが…)。
例えばユーザーアカウントを登録した際には上の図のテーブルに登録されたユーザーの情報がレコード(行)として追加されることになります。
実際のアプリを動作させている際に、ユーザーアカウントがうまく登録されているかどうかを確認したりする際に便利なので、こういったテーブルの中身をお手軽に確認できる環境があるとウェブアプリの開発が捗ると思います。
このプラグインについては下記ページでも紹介していますので、使い方等の詳細は下記ページを参考にしていただければと思います。
【Django/VSCode】データベースのテーブルの中身を表示する以上で、ログイン機能を持つウェブアプリを開発していく上での大枠を作成できたことになります。ここからは、ログイン機能を実現するために必要なこと で紹介した各項目を1つ1つの実現の仕方の説明・具体的な実装例の紹介をしていきたいと思います。
ユーザーアカウントの登録
では、まずはユーザーアカウントの登録を実現していきたいと思います。
ユーザーアカウントの登録は、ユーザーの情報(ユーザー名やパスワードなど)をデータベースにレコードとして保存することで実現することが出来ます。
より具体的には、まず登録するユーザーの情報の入力フォームを表示し、その入力フォームからユーザーの情報が送信されてきた際に、そのユーザーの情報をデータベースにレコードとして保存してやることでユーザーアカウントの登録を実現することが出来ます。
ユーザーアカウント登録用の Model の作成
上記のレコードの保存において、レコードの保存先のテーブルは「ユーザーの情報を管理する Model」から生成されるテーブルとなります。
そのため、ユーザーアカウント登録や後述で説明するログインを行うためには、あらかじめ「ユーザーの情報を管理する Model」を定義しておく必要があります。
ただ、前述の通り、今回は「ユーザーの情報を管理する Model」として Django に標準で用意されている User
をそのまま利用しますので、今回は Model の定義は不要となります(models.py
は変更不要)。
ユーザーアカウント登録用の Form の作成
また、一般的なウェブアプリやウェブサイトにおいては、ユーザーアカウント登録時にはユーザー名等のユーザーを識別するためのユニークな情報(他の人と重複しない情報)とパスワードの入力が必要な場合が多いです。
さらに、確認用としてパスワードの入力を2回要求されるのが一般的だと思います。
このような入力フォームは、Django に用意されている UserCreationForm
を継承して Form を定義することで簡単に実現することが出来ます。
例えば、下記のように login_app/forms.py
を新規作成してやれば、ユーザアカウント登録用の入力フォーム SignupForm
を定義することが出来ます。
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class SignupForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
UserCreationForm
は forms.ModelForm
のサブクラスであり、基本的には forms.ModelForm
のサブクラスとして定義したフォームと同様の使い方をすることが出来ます。
forms.ModelForm
では model
に指定したモデルの持つフィールドに基づいて入力フォームを作成することができます。上記では model = User
を指定しているため、User
モデルの持つフィールドに合わせて入力フォームを作成することができることになります。
ただ、User
モデルにはユーザー名やパスワードだけでなく、「最終ログイン日時」や「アカウント作成日時」、「ユーザの持つ権限」などを設定するフィールドを持っており、全てをフォームとして表示してしまうとユーザーの入力が大変になってしまいます。
そのため、fields
を指定して表示するフィールドを下記の4つに絞るようにしています。
'username'
:ユーザー名'email'
:メールアドレス'password1'
:パスワード'password2'
:パスワード(確認用)
'password1'
と 'password2'
に関しては User
モデルのフィールドに存在しないのですが、UserCreationForm
のサブクラスとしてフォームを定義することで入力フォームとして表示することができるようになります(fields
に指定することができるようになる)。
ユーザーアカウント登録用の Template の作成
次に、ユーザーアカウント登録用のフォームをページ上に表示するための Template を login_app/templates/login_app/signup.html
として作成していきたいと思います(新規作成が必要なファイルになります)。
ユーザーアカウント登録用のフォームといっても、通常のフォームと同様にして Template に組み込むことが出来ます。
例えば、View から先ほど定義した SignupForm
のインスタンスを form
として受け取るのであれば、{{ form.as_p }}
と Template に記述しておけば、下記の4つの入力フィールドを持つフォームが段落形式でページに表示されることになります。
'username'
:ユーザー名'email'
:メールアドレス'password1'
:パスワード'password2'
:パスワード(確認用)
もちろん CSS 等を利用すればユーザーアカウント登録用のフォームの見た目を良くすることもできますが、今回はログインの機能に焦点を当てて解説していきたいため、下記のようにシンプルな login_app/templates/login_app/signup.html
を新規作成していきたいと思います。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ユーザー登録</title>
</head>
<body>
<h1>ユーザー登録</h1>
<form action="{% url 'signup' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="登録"></p>
</form>
</body>
</html>
View からは下記をキーとする辞書を受け取ることを期待した Template となっています。
'form'
:ユーザーアカウント登録用のフォーム
ユーザーアカウント登録用の View の作成
ユーザーアカウント登録のための作業として、最後に View を作成していきたいと思います。
事前準備(プロジェクトやアプリの作成など) で login_app/views.py
に signup_view
関数を用意しましたので、この関数を変更することで、/login_app/signup/
へのリクエスト時のユーザーアカウント登録のページの表示、さらには送信されたフォームに従ったユーザーアカウントの登録を実現していきます。
具体的には、GET メソッド(POST メソッド以外)でリクエストされた際には、Template を描画してユーザーアカウント登録のページの表示を行うように signup_view
関数を変更していきます。
この際は、先ほど作成したテンプレートを render
関数で描画すれば良いだけです。これにより、下記の4つの入力フィールドを持つフォームがページに表示されます。
'username'
:ユーザー名'email'
:メールアドレス'password1'
:パスワード'password2'
:パスワード(確認用)
また、POST メソッドでリクエストされた際には、上記の4つの情報がデータとして送信されてきますので、これらのデータに基づいた情報を User
モデルのインスタンスとしてデータベースに保存するように signup_view
関数を変更していきます。このデータベースへの保存によってユーザーアカウントが登録されることになります。
このデータベースの保存は、login_app/forms.py
に定義した SignupForm
のインスタンスを POST で送信されてきたデータから生成し、そのインスタンスに save
メソッドを実行させることで実現できます。
ただし、単にデータベースに保存するだけではダメで、'username'
が他のユーザーと重複している場合や 'password1'
と 'password2'
が不一致している場合はデータベースへの保存を行わないようにする必要があります(ユーザーアカウントの登録に失敗するようにする)。
要は POST で送信されてきたデータの妥当性の検証が必要ということです。
この妥当性の検証は、通常の forms.ModelForm
のサブクラスのフォームと同様に、POST で送信されてきたデータから生成したインスタンスに is_valid
メソッドを実行させることで行うことが出来ます。
ですので、is_valid
メソッドが true
を返却した場合のみ save
メソッドを実行させるようにすれば、妥当でないユーザーアカウントの登録を防ぐことができるようになります('username'
が他のユーザーと重複している場合や 'password1'
と 'password2'
が不一致している場合)。
上記の解説内容を考慮して作成した signup_view
関数は下記のようになります(SignupForm
の import
が必要である点に注意してください)。
from django.shortcuts import render
from .forms import SignupForm
def signup_view(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
form.save()
else:
form = SignupForm()
param = {
'form': form
}
return render(request, 'login_app/signup.html', param)
略
上記の signup_view
関数を見ていただければ分かる通り、ユーザーアカウントの登録に成功しても再度ユーザーアカウント登録ページが表示されることになります。
なので、ちょっとユーザーアカウントの登録に成功したことが分かりにくいです…。
上記では実装を簡単にするためにこのような動作になっていますが、ユーザーアカウント登録成功時に続けてログイン処理を行うことも可能です。この実例は最後の ログイン機能実現用のスクリプト で紹介していますので、興味があればそちらを参考にしていただければと思います。
ユーザーアカウント登録の動作確認
以上によりユーザーアカウント登録をができるようになったはずなので、ここで動作確認をしておきましょう!
まずはいつも通り下記コマンドで Django の開発用ウェブサーバーを起動させましょう。
% python manage.py runserver
次に、ウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/signup/
ここまで解説してきた通りに変更をしてきてくださった方であれば、下の図のようなページが表示されるはずです。この入力フォーム部分が SignupForm
から作成したフォームになります。
さらに、上の入力フォームから順に「ユーザー名」「メールアドレス」「パスワード」「パスワード(確認用)」を入力して 登録
ボタンを押下すれば、ユーザーアカウントの登録が行われます。
ただ、現状はユーザーアカウントの登録が行われてもページが遷移したりするわけではないため、本当に登録が行われたかどうかが確認しづらいと思います…。
ユーザーアカウントが登録されてるかどうかを確認したい場合は、データベースの auth_user
テーブルの中身を確認してみてください。登録したユーザーのユーザー名が username
の列に、メールアドレスが email
の列に設定されているレコードが見つかるはずです(見つからない場合はユーザーアカウントの登録に失敗していると思われます)。
また、重複する「ユーザー名」を入力して登録しようとしたり、「パスワード」と「パスワード(確認用)」が異なる状態で登録しようとしたりした場合は下記のようなエラーメッセージが表示されるようになっており、この場合はユーザーアカウントの登録ができないようになっています。
A user with that username already exists.
The two password fields didn’t match.
以降の動作確認を行う際にはユーザーアカウントは複数存在した方が良いので、上記のフォームから3つ程度のユーザーアカウントの登録を行なっておいてください。
スポンサーリンク
ログイン
一応ユーザーアカウントが登録できるようになったので、次はログインを実現していきます。
ログインを実現する上で必要になるのが、ログインフォームの表示、さらにはログインフォームから送信されてきたユーザーの情報で認証を行い、認証 OK の場合にそのユーザーの状態をログイン状態に設定する処理となります。
認証 OK とは、送信されてきたユーザー名がユーザーアカウントとして登録されている&パスワードが正しいことを言います。
難しそうですが、Django に用意されている関数を利用すれば、これらも簡単に実現することが可能です。
ログイン用の Form の作成
まずはログインフォームを定義していきましょう!
ログインフォームに関しては、AuthenticationForm
のサブクラスとしてフォームを定義することで簡単に実現することが出来ます(そのまま AuthenticationForm
を利用するのでも問題ありませんが、今回は今後の拡張を見据えてログインフォームを別途作成するようにしています)。
AuthenticationForm
は Django に標準で用意されているフォームであり、ユーザー名とパスワードの入力受付を行う認証用のフォームとなります。
例えば、下記のように login_app/forms.py
を変更してやれば、ユーザー名とパスワードを入力してログインを行うフォームを定義することが出来ます(AuthenticationForm
の import
を忘れないように注意してください)。
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
class SignupForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class LoginForm(AuthenticationForm):
pass
ログイン用の Template の作成
次に、ログイン用のフォームをページ上に表示するための Template を login_app/templates/login_app/login.html
として作成していきたいと思います(新規作成が必要なファイルになります)。
ユーザーアカウント登録用の Template の作成 の時同様に、通常のフォームを表示する時と同様に、{{ form.as_p }}
等を利用すれば簡単にログインフォームを Template に組み込むことが出来ます。
今回は、下記のように login_app/templates/login_app/login.html
を新規作成していきたいと思います。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ログイン</title>
</head>
<body>
<h1>ログイン</h1>
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="ログイン"></p>
</form>
</body>
</html>
View からは下記をキーとする辞書を受け取ることを期待した Template となっています。
'form'
:ログイン用のフォーム
ログイン用の View の作成
ログイン実現のための作業の最後として、続いて View を作成していきます。
事前準備(プロジェクトやアプリの作成など) で login_app/views.py
にlogin_view
関数を用意しましたので、この関数を変更することで、/login_app/login/
へのリクエストがあった際のログインページの表示、さらにはフォームから送信されてきたユーザー名とパスワードの認証とログインの処理を実現していきます。
より具体的には、GET メソッド(POST メソッド以外)でリクエストされた際はアカウント登録時と同様に Template を描画してログインのページの表示を行うようにlogin_view
関数を変更していきます。
さらに、POST メソッドでリクエストされた際には送信されてきたユーザー名とパスワードで認証を行い、認証 OK の場合にユーザーをログイン状態に設定するようにしていきます。
AuthenticationForm
のサブクラスのフォームの場合、認証に関しては、このフォームのインスタンスに is_valid
メソッドを実行させることで実現できます。
もう少し詳しくいうと、is_valid
メソッドの中で authenticate
という関数が実行され、送信されてきたユーザー名がユーザーアカウント登録されているか、さらにはパスワードが正しいかどうかを判断してくれます。
ユーザー名が登録されており、さらにパスワードが正しい場合、is_valid
メソッドは True
を返却しますので、この場合のみユーザーをログイン状態にしてやれば良いことになります。
さらに、ユーザーをログイン状態にする処理は login
関数を実行することで実現できます。
この login
関数を実行する際には、ログイン状態に移行させるユーザー(User
モデルのインスタンス)を引数に指定する必要がありますが、このユーザーに関しては AuthenticationForm
のサブクラスのフォームのインスタンスに get_user
メソッドを実行させることで取得することが出来ます。
この辺りを考慮して変更を行った login_view
関数は下記のようになります(import
をいくつか追加しているので注意してください)。
from django.shortcuts import render
from .forms import SignupForm, LoginForm
from django.contrib.auth import login
def signup_view(request):
略
def login_view(request):
if request.method == 'POST':
form = LoginForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
if user:
login(request, user)
else:
form = LoginForm()
param = {
'form': form,
}
return render(request, 'login_app/login.html', param)
略
「認証」や「ログイン」と聞くと難しそうに感じると思いますが、実際の関数を見てみると思ったより簡単であると感じる方が多いのではないかと思います。こんな感じで、Django に用意されているクラスや関数を利用することで、ログイン等の様々な機能を簡単に実現することが可能です。
ただし、上記の login_view
関数で行われるのは認証とログインだけであり、本当はログイン後に別のページにリダイレクトするような処理が必要になります。
これについては後述の ログイン後のリダイレクト で解説していきます。
ログインの動作確認
ひとまずログイン自体はできるようになったため、ログインを実際に行ってみましょう!
まずは Django 開発用ウェブサーバーを起動後、ウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/login/
おそらく下の図のようなページが表示されるはずです。下側の入力フォームが LoginForm
から作成したフォームになります。
続いて、Username
と Password
の入力欄に、ユーザーアカウント登録の動作確認 で登録したユーザーのユーザー名とパスワードを入力し、ログイン
ボタンを押下してみてください。
正直ボタンを押下してもページが遷移しないのでログインできたことが分かりにくいと思いますが、データベースの auth_user
のテーブルを確認することでログインできたことを確認することが出来ます。
具体的には、ログインを行なったユーザーに対応するレコードの last_login
のフィールドに ログイン
ボタンを押下した時の日時が格納されているはずです。last_login
はユーザーが最終ログインした日時を格納するフィールドであり、ここに日時が格納されていることから、先程のログインボタン押下によってログインが行われたことを確認できると思います。
さらに、ログインによって django_session
のテーブルにレコードが追加されているはずです。
このレコードは、ログイン状態のユーザーを見分けるための重要なデータとなります。
ウェブブラウザからウェブアプリに対して HTTP リクエストを送信する時には(ウェブアプリにアクセスする時には)、session_key
がリクエストのヘッダーに設定されることになります。
そして、その設定された session_key
と同じ値を持つレコードが django_session
テーブルに存在する場合、その HTTP リクエストを送信してきたウェブブラウザのユーザーをログイン状態と判断するようになっています。
逆に session_key
を持つレコードが django_session
に存在しない場合は、ウェブブラウザのユーザーをログイン状態でないと判断します。
このようにしてユーザーがログイン状態であるかどうかを判断するようになっているため、ログインが行われるたびにユーザーごとに django_session
にレコードが追加される(or レコードが更新される)ようになっています。
ちなみに、次に説明する「ログアウト」を行うことで、ログアウトを行なったユーザーに対する django_session
のレコードが削除されることになります。
現状だとデータベースの変化からしかログインされた状態が判断できないのでちょっと分かりにくいかもしれないですが、前述のデータベースの結果より、ここまでの変更でログインができるようになったことを確認できると思います。
スポンサーリンク
ログアウト
続いてはユーザーのログアウトを実現していきたいと思います。
ログイン時は、フォームから送信されてきたユーザー名やパスワードから認証を行い、認証 OK の場合のみ login
関数を実行するようにしていましたが、ログアウトの場合はログアウトページ表示時に単に logout
関数を実行すれば良いだけです。
なので、ログイン自体もそんなに大変ではなかったと思いますが、ログアウトはさらに簡単に実現することが出来ます。
ログアウト用の Template の作成
ということで、まずはログアウト用の Template を作成していきたいと思います。
今回はログアウトページの Template として、下記のような login_app/templates/login_app/logout.html
を新規作成していきたいと思います。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ログアウト</title>
</head>
<body>
<p>ログアウトしました...</p>
</body>
</html>
ログアウト用の View の作成
続いて、ログアウト用の View を作成していきます。
最低限必要なのは、前述で紹介した logout
関数の実行と、Template の render
関数で描画くらいだと思います。
もちろん、ログアウト後にリダイレクトを行なって他のページに自動的に遷移させるようなことをしても良いと思いますが、今回は最低限必要な処理のみを行います。
このような View は、logout_view
関数を下記のように変更することで実現することが出来ます(logout
の import
が必要である点に注意してください)。
from django.shortcuts import render
from .forms import SignupForm, LoginForm
from django.contrib.auth import login, logout
def signup_view(request):
略
def login_view(request):
略
def logout_view(request):
logout(request)
return render(request, 'login_app/logout.html')
略
ログアウトの動作確認
以上によってログアウトが実現できるようになったため、ログアウトの動作確認を行なっていきたいと思います。
まずは Django 開発用ウェブサーバーを起動後、ログインの動作確認 に従ってユーザーログインを行っておいてください。
次に、データベースの django_session
テーブルを確認してみてください。ログインを行なったことで django_session
のレコードが追加されているはずです(もしくは更新されている)。
続いてウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/logout/
すると、下の図のような画面が表示されるはずです。
さらに、再度 django_session
テーブルを確認してみてください。先ほど存在していたレコードが削除されているはずです(複数存在していた場合は1つ減っている)。
ログインの動作確認 で解説した通り、django_session
のレコードはログインが行われるたびにユーザーごとに追加(or 更新)されるデータであり、ログアウトを行うことでログアウトしたユーザーに対するレコードが削除されることになります。
上記の結果より、django_session
のレコードが削除されており、ユーザーのログアウトが行われていることを確認することができると思います。
参考:自動ログアウト
Django においては、一定時間が経過すると自動的にユーザーのログアウトが行われるようになっています。
上の図の django_session
テーブルの expire_date
フィールドの値が、ユーザーの自動ログアウトが行われる日時を示すものになります。おそらくログインしてから2週間後にログアウトされるように日時が格納されているはずです。
この自動ログアウトまでの時間は変更することが可能で、この変更方法は下記ページで解説していますので、詳しく知りたい方は是非下記ページを読んでみてください。
【Django】自動ログアウト時間の設定方法ログインユーザーに応じたページ表示
続いて、ログインユーザーに応じたページの表示を実現していきたいと思います。
ログインユーザーに応じてページを表示するためには、まずはページを表示しているユーザーのオブジェクト(User
モデルのインスタンス)を取得する必要があります。
既にログイン中の場合、このユーザーのオブジェクトは View の関数に引数として渡される request
の user
データ属性から取得することが出来ます。
詳しく説明すると、ページ表示時にはウェブブラウザからサーバーに対して HTTP リクエストが送信されますが、そのウェブブラウザでログインしている場合、そのリクエストのヘッダーには先程紹介した session_key
がセットされるようになります
そして、その session_key
から Django 本体によってユーザーのオブジェクトが取得され、それが request.uesr
にセットされた状態で View 関数が実行されるようになります
そのため、View の request.user
から User
モデルのフィールドに設定されているデータ(username
や email
など)を取得し、それをページに表示してやれば、ログインユーザーに応じたページの表示を実現することができることになります。
今回はユーザーを管理するモデルとして User
をそのまま利用していますが、ユーザーを管理するモデルを自身でカスタマイズしてアプリに応じた情報をモデルのフィールドに設定できるようにしておけば、上記のような手順でさらに様々な情報をページに表示することも可能になります(例えばユーザーのアバターを表示したり、ユーザーの投稿した画像を表示したり)。
ログインユーザーに応じたページ表示用の Template の作成
では実際にログインユーザーに応じたページの表示を行なっていきましょう!
まずは Template から作成していきたいと思います。
今回は、ログインユーザーに応じた情報を表示するページとして2つのページを用意していきたいと思いますので、2つの Template を作成していきます。
1つ目はログインユーザーの情報(ユーザー名とメールアドレスとアカウント登録日)を表示するページの Template とし、2つ目はログインユーザー以外のユーザーの情報(ユーザー名とメールアドレス)を表示するページの Template としたいと思います。
まずは1つ目の Template として、下記のように login_app/templates/login_app/user.html
を新規作成します。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>あなたの情報</title>
</head>
<body>
<h1>{{user.username}}</h1>
<p>連絡先:{{user.email}}</p>
<p>アカウント作成日:{{user.date_joined}}</p>
</body>
</html>
次に2つ目の Template として、下記のように login_app/templates/login_app/other.html
を新規作成します。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>他のユーザーの情報</title>
</head>
<body>
<h1>他のユーザーの情報</h1>
{% for user in users %}
<h2>{{user.username}}</h2>
<p>連絡先:{{user.email}}</p>
{% endfor %}
</body>
</html>
user.html
ではログインユーザーの情報のみを表示するため、User
モデルのインスタンスを user
として受け取ることを期待する Template となっています。
そして、user
のデータ属性(username
など)をページに組み込む形の Template となっています。
それに対し、other.html
ではログインユーザー以外のユーザーの情報を表示するため、複数の User
モデルのインスタンスが格納された list
や queryset
を users
として受け取ることを期待する Template となっています。
そして、for
文の中で1つ1つの User
モデルのインスタンスを user
として取得し、user
のデータ属性(username
など)をページに組み込む形の Template となっています。
ログインユーザーに応じたページ表示用の View の作成
続いて View を作成していきます。
まず、前述の通り、ログインユーザーのオブジェクトは request.user
にセットされていますので、ログインユーザーの情報をページに表示するためには、これをページに組み込む Template に request.user
を渡してやれば良いことになります。
そのため、ログインユーザー自体の情報を表示する際の Vew は、user_view
関数を下記のように変更することで実現することが出来ます。
from django.shortcuts import render
from .forms import SignupForm, LoginForm
from django.contrib.auth import login, logout
def signup_view(request):
略
def login_view(request):
略
def user_view(request):
user = request.user
params = {
'user': user
}
return render(request, 'login_app/user.html', params)
略
ただし、request.user
にセットされているのはあくまでもログインユーザーのオブジェクトであり、他のユーザーの情報は request.user
から取得することはできません。
ですので、ログインユーザー以外の情報をページに表示したい場合は、データベースから別途ログインユーザー以外のオブジェクト(User
モデルのインスタンス)を取得する必要があります。
上記を考慮して変更を行なった other_view
関数は次のようになります。User
の import
が必要である点に注意してください。
from django.shortcuts import render
from .forms import SignupForm, LoginForm
from django.contrib.auth import login, logout
from django.contrib.auth.models import User
def signup_view(request):
略
def login_view(request):
略
def user_view(request):
略
def other_view(request):
users = User.objects.exclude(username=request.user.username)
params = {
'users': users
}
return render(request, 'login_app/other.html', params)
ログインユーザー以外のオブジェクトを取得しているのが User.objects.exclude
の部分になります(username
フィールドが request.user.username
と異なる User
モデルのオブジェクトを取得している)。
また、この exclude
の返却値は User
モデルの queryset
であり、これをそのまま Template に渡すようにしています。これにより、other.html
の for
文の中で1つ1つの User
モデルのインスタンスの情報が Template で組み込まれることになります。
ログインユーザーに応じたページ表示の動作確認
以上で、簡単ですがログインユーザーに応じたページ表示ができるようになったことになりますので動作確認をしておきましょう!
まずは Django の開発用ウェブサーバーを起動し、ログインの動作確認 に従ってユーザーのログインを行なっておいてください。
続いてウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/user/
開くと、ログイン中のユーザーのユーザー名とメールアドレス、アカウント登録日時が表示されることを確認することができると思います。
さらに、今度はウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/other/
そうすると、ログイン中のユーザー以外のユーザー名とメールアドレスが一覧表示されることを確認することができると思います。
次は、ログインの動作確認 に従って先ほどは異なるユーザーでログインを行い、その後に再度ウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/user/
ウェブブラウザからログインしているユーザーが変わったので、今度は先ほどとは異なる情報が表示されていることが確認できると思います。
同様に、下記 URL を開いた場合も先ほどとは異なる情報が表示されていることが確認できると思います。
http://localhost:8000/login_app/other/
このような結果から、ここまで解説してきた内容に基づいて View や Template を作成すれば、ログイン中のユーザーに応じたページ表示を実現することが可能であることを理解していただけるのではないかと思います。
未ログインユーザーからのアクセス禁止
ただし、現状では未ログインユーザーであっても下記のページを閲覧することが可能です。
http://localhost:8000/login_app/user/
http://localhost:8000/login_app/other/
つまり、ログインしなくてもアプリが利用可能ということです。
ただ、特に会員制のウェブアプリを開発する上では、未ログインユーザーから閲覧されたくないページもあると思います。
そのため、続いては未ログインユーザーに特定のページへのアクセスを禁止させる方法について解説します。
まず、アクセス禁止はリダイレクトを利用して実現します。要は、未ログインユーザーから特定のページへのアクセスがあった場合にリダイレクトを行なって他のページに自動的に遷移するようにさせます。
さらに、この未ログインユーザーからの特定のページへのアクセスがあった際のリダイレクトは、そのページに対応する View の関数に login_required
デコレータを指定することで実現することが出来ます。
また、リダイレクト先のページは settings.py
で LOGIN_URL
を指定することで好きなページに設定することが出来ます。
例えば LOGIN_URL
にログインページのパスを指定しておけば、未ログインユーザーから特定のページのアクセスがあった際に自動的にログインページに遷移させることが出来ます。
未ログインユーザーからのアクセス禁止用の View の設定
では、実際に未ログインユーザーからのアクセスがあった際に、ログインページにリダイレクトを行うことでそのページにアクセスできないようにしていきたいと思います。
まずは login_app/view.py
において、下記のように未ログインユーザーからのアクセスを禁止したいページに対応する View の関数の前に @login_required
を指定するようにします。login_required
の import
が必要な点に注意してください。
from django.shortcuts import render
from .forms import SignupForm, LoginForm
from django.contrib.auth import login, logout
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def signup_view(request):
略
def login_view(request):
略
def logout_view(request):
略
@login_required
def user_view(request):
略
@login_required
def other_view(request):
略
上記の変更により、アクセスしてきたのが未ログインユーザーの場合、user_view
や other_view
が実行されるのではなくリダイレクトが行われるようになります。
つまり、次の2つのページへの未ログインユーザーのアクセスを禁止することが出来ます。
http://localhost:8000/login_app/user/
http://localhost:8000/login_app/other/
未ログインユーザーからのアクセス禁止用の settings.py
の設定
さらに、login_project/settings.py
に LOGIN_URL
を指定することで、リダイレクト先のページの設定を行います。
今回は LOGIN_URL
に /login_app/login/
を指定することで、未ログインユーザーからのアクセス時にログインページにリダイレクトするようにしたいと思います。
これは、login_project/settings.py
に下記のように LOGIN_URL
の指定を追記することで実現することが出来ます。追記する場所は login_project/settings.py
の最後部分で良いと思います。
LOGIN_URL = '/login_app/login/'
未ログインユーザーからのアクセス禁止の動作確認
では、未ログインユーザーからのアクセスが本当に禁止されるようになったかを確認しておきましょう!
まずは、ログアウトの動作確認 の手順に従って事前にログアウトを行なっておいてください。
続いて、ウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/user/
すると、自動的にログインページが表示されるようになったことを確認することができると思います。
続いて、表示されたログインページでログインを行なった後に、再度上記 URL をウェブブラウザで開いてみてください。
すると、今度はログインページではなく、ログインしたユーザーの情報が表示されて上記 URL にアクセスできるようになったことが確認できると思います。
下記の URL を開いた際にも同様のことが確認できるはずです。
http://localhost:8000/login_app/other/
これらの結果より、@login_required
を利用することで未ログインユーザーのアクセスを禁止することが可能であることが確認できると思います。
スポンサーリンク
ログイン後のリダイレクト
ここまでの実装によってウェブアプリにログイン機能を持たせることが出来たことになります。
ただ、現状ではログインを行なってもそのままログインページが表示されるだけなので、ウェブアプリの動作としてイマイチです。
次は、ログイン後に別のページにリダイレクトさせるようにしていきたいと思います。
リダイレクト先を固定のページとする
リダイレクト先が固定で良いのであれば、ログインを行う View の関数の中で、login
実行後に redirect
関数の実行結果を return
してやれば良いだけです。
redirect
実行時には to
引数にリダイレクト先のパスや URL を指定します。
例えば、下記のように login_app/views.py
の login_view
を変更してやれば、ログイン後に http://localhost:8000/login_app/user/
にリダイレクトされるようになります(redirect
の import
が必要である点に注意してください)。
from django.shortcuts import render, redirect
from .forms import SignupForm, LoginForm
from django.contrib.auth import login, logout
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def signup_view(request):
略
def login_view(request):
if request.method == 'POST':
form = LoginForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
if user:
login(request, user)
return redirect(to='/login_app/user/')
else:
form = LoginForm()
param = {
'title': 'ログイン',
'form': form,
}
return render(request, 'login_app/login.html', param)
略
リダイレクト先を元々のアクセスページとする
また、ログイン後のリダイレクト先を、元々ユーザーがアクセスしようとしていたページとすることもできます。
未ログインユーザーからのアクセス禁止 での @login_required
の対応によって、未ログインの状態で下記ページにアクセスした場合、ログインページにリダイレクトされるようになりました。
http://localhost:8000/login_app/user/
http://localhost:8000/login_app/other/
例えば前者のページにアクセスしようとしてログインページにリダイレクトされた場合、ログイン後には前者のページにリダイレクトされた方がユーザーにとって便利ですし、後者のページにアクセスしようとしてリダイレクトされた場合は、ログイン後には後者のページにリダイレクトされた方が便利です。
このように、@login_required
によってログインページにリダイレクトされた場合、固定のページではなく、元々ユーザーがアクセスしようとしていたページにリダイレクトを行なった方が良い場合も多いです。
次は、ログイン後のリダイレクト先を「元々ユーザーがアクセスしようとしていたページ」にするための方法を解説していきます。
まずポイントになるのが、未ログインユーザーがログインページにリダイレクトされる際の URL になります。
実際に試していただければ分かると思いますが、例えば未ログインの状態で http://localhost:8000/login_app/user/
にアクセスした場合はログインページにリダイレクトされることになりますが、このリダイレクト先の URL にはクエリストリングとして next
パラメータが付与されることになります(@login_required
によって付与される)。
そして、この next
パラメータの値として、元々ユーザーがアクセスしようとしていたページのパスが設定されています。
そのため、ログイン後のリダイレクト先を next
パラメータの値のパスとしてやれば、ログイン後のリダイレクト先を元々ユーザーがアクセスしようとしていたページとすることが出来ます。
ログイン後のリダイレクト先を next
パラメータの値のパスに設定するためには、まず login_app/views.py
の login_view
関数を下記のように変更し、
from django.shortcuts import render, redirect
from .forms import SignupForm, LoginForm
from django.contrib.auth import login, logout
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def signup_view(request):
略
def login_view(request):
if request.method == 'POST':
next = request.POST.get('next')
form = LoginForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
if user:
login(request, user)
if next == 'None':
return redirect(to='/login_app/user/')
else:
return redirect(to=next)
else:
form = LoginForm()
next = request.GET.get('next')
param = {
'form': form,
'next': next
}
return render(request, 'login_app/login.html', param)
略
さらに login_app/templates/login_app/login.html
を下記のように変更します(input
タグを1つ追加しています)。
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ログイン</title>
</head>
<body>
<h1>ログイン</h1>
<form action="{% url 'login'%}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="hidden" name="next" value="{{next}}"></p>
<p><input type="submit" value="ログイン"></p>
</form>
</body>
</html>
login.html
関数では、View から渡された next
をユーザー名やパスワードと一緒に送信を行うように変更しています。
これにより、ログインボタンが押下されて login_view
関数がメソッド POST で実行される際に、request.POST['next']
に next
パラメータの値のパスが設定されるようになります。
また、login_view
関数は大きく2つの変更をしており、1つ目は上記の next
パラメータの値を Template に渡すための変更になります(メソッドが POST 以外の場合の処理)。
さらに、メソッドが POST の場合は、送信されてきた next
パラメータの値を redirect
の引数に設定するようにしています。これにより、ログイン時に元々ユーザーがアクセスしようとしていたページにリダイレクトが行われるようになります。
ただし、next
パラメータが設定されていないような場合もあるため(直接ログインページにアクセスされた場合)、その場合は固定のページにリダイレクトするようにしています。
ログイン後のリダイレクトの動作確認
最後に リダイレクト先を元々のアクセスページとする で紹介したスクリプトを用いて、ログイン後のリダイレクトの動作確認を行なっていきたいと思います。
まずは Django の開発用ウェブサーバーを起動し、ログアウトの動作確認 に従ってユーザーのログアウトを行なっておいてください。
続いてウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/user/
開くとリダイレクトが行われて下の図のログインページが表示されると思います。
ポイントは、上の図のように、ウェブブラウザのアドレスバー部分の URL の ?next=
以降に元々アクセスしようとしていたページのパスが表示されているところになります。
さらに、登録済みのユーザー名とパスワードを入力してログインを行なってみてください。
ログインに成功した場合、?next=
以降で示されていたパスに自動的にリダイレクトされるはずです。
続いて、再度 ログアウトの動作確認 に従ってユーザーのログアウトを行い、次はウェブブラウザで下記 URL を開いてみてください。
http://localhost:8000/login_app/other/
開くと、先ほど同様にログインページが表示されますが、先ほどとは URL の ?next=
以降のパスが変化していることが確認できるはずです。これは、先ほどとは元々アクセスしようとしていたページが異なるからです。
さらに、再度登録済みのユーザー名とパスワードを入力してログインを行なってみてください。ログインに成功した場合、?next=
以降で示されていたパスに自動的にリダイレクトされるはずです。
最後に、再度 ログアウトの動作確認 に従ってユーザーのログアウトを行い、次はウェブブラウザで下記 URL を開いて直接ログインページにアクセスしてみてください。
http://localhost:8000/login_app/login/
当然ログインページが表示されますが、ここまでの動作結果とは異なり、URL に ?next=
が存在しないことを確認できると思います。このように直接ログインページにアクセスされた場合は URL に ?next=
は存在しません。
ただ、この場合であっても、ログインを行えば /login_app/user/
にリダイレクトされることが確認できるはずです。
3つのパターンの動作確認を行いましたが、いずれの場合であっても、ログイン後のリダイレクトによってアプリの利便性が向上したことを確認できると思います。
ログイン機能実現用のスクリプト
以上で、ログイン機能を実現するために必要な実装についての解説は終了です。
ここまで各動作を実現するために個別にスクリプトを紹介してきましたので、ここで forms.py
・views.py
・各種テンプレートファイルをまとめて紹介しておきます。
forms.py
はここまで紹介したものと全く同じです。ですが、views.py
やテンプレートに関しては、ここまで紹介してきたものに比べて下記を変更して多少アプリを使用しやすくしていますので、これらの点も参考にしていただければと思います。
views.py
:ユーザーアカウント登録時にログインを同時に行うように変更- テンプレート:他のページへのリンクを追加
他のファイル等の作成に関しては 事前準備(プロジェクトやアプリの作成など) で紹介していますので、まだ読んでいない方は こちら を参考にしていただければと思います(settings.py
に関しては 未ログインユーザーからのアクセス禁止用の settings.py の設定 で紹介した変更も必要なので注意してください)。
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
class SignupForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class LoginForm(AuthenticationForm):
pass
from django.shortcuts import render, redirect
from .forms import SignupForm, LoginForm
from django.contrib.auth import login, logout
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
def signup_view(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect(to='/login_app/user/')
else:
form = SignupForm()
param = {
'form': form
}
return render(request, 'login_app/signup.html', param)
def login_view(request):
if request.method == 'POST':
next = request.POST.get('next')
form = LoginForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
if user:
login(request, user)
if next == 'None':
return redirect(to='/login_app/user/')
else:
return redirect(to=next)
else:
form = LoginForm()
next = request.GET.get('next')
param = {
'form': form,
'next': next
}
return render(request, 'login_app/login.html', param)
def logout_view(request):
logout(request)
return render(request, 'login_app/logout.html')
@login_required
def user_view(request):
user = request.user
params = {
'user': user
}
return render(request, 'login_app/user.html', params)
@login_required
def other_view(request):
users = User.objects.exclude(username=request.user.username)
params = {
'users': users
}
return render(request, 'login_app/other.html', params)
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ユーザー登録</title>
</head>
<body>
<h1>ユーザー登録</h1>
<form action="{% url 'signup' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="submit" value="登録"></p>
</form>
</body>
</html>
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ログイン</title>
</head>
<body>
<h1>ログイン</h1>
<form action="{% url 'login'%}" method="post">
{% csrf_token %}
{{ form.as_p }}
<p><input type="hidden" name="next" value="{{next}}"></p>
<p><input type="submit" value="ログイン"></p>
</form>
<p><a href="{% url 'signup'%}">ユーザー登録</a></p>
</body>
</html>
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ログアウト</title>
</head>
<body>
<p>ログアウトしました...</p>
<p><a href="{% url 'login'%}">ログイン</a></p>
</body>
</html>
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>あなたの情報</title>
</head>
<body>
<h1>{{user.username}}</h1>
<p>連絡先:{{user.email}}</p>
<p>アカウント作成日:{{user.date_joined}}</p>
<p><a href="{% url 'other'%}">他のユーザーの情報</a></p>
<p><a href="{% url 'logout'%}">ログアウト</a></p>
</body>
</html>
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>他のユーザーの情報</title>
</head>
<body>
<h1>他のユーザーの情報</h1>
{% for user in users %}
<h2>{{user.username}}</h2>
<p>連絡先:{{user.email}}</p>
{% endfor %}
<p><a href="{% url 'user'%}">あなたの情報</a></p>
<p><a href="{% url 'logout'%}">ログアウト</a></p>
</body>
</html>
まとめ
このページでは、Django におけるログイン機能の実現方法について解説しました!
ログイン機能を実現する上でメインになるのは当然「ログイン処理」になりますが、アプリにログイン機能を持たせる意味を考慮すると、下記の6つくらいも同時に実現した方が良いと思います。
- ユーザーアカウントの登録
- ログイン
- ログイン後のリダイレクト
- 未ログインユーザーからのアクセス禁止
- ログインユーザーに応じたページ表示
- ログアウト
それぞれ難しそうな処理にも思えますが、基本的には Django に用意されている関数やクラスを利用すれば簡単に実現可能です。
ウェブアプリにログイン機能を持たせることができれば、開発できるウェブアプリの幅を大きく広げることが出来ます!ウェブアプリを開発していきたいという方は、是非このページで紹介した内容は理解しておいてください!
また、今回は View を関数ベースでログイン機能を実現しましたが、ページの冒頭でも述べたように、LoginView
などの Django に用意されているクラスを継承しながらクラスベースで View を作成することで更に簡単にログイン機能を実現することも出来ます。
その具体的な方法に関しては下記ページで解説していますので、クラスベースの View でログイン機能を実現したい場合は是非読んでみてください!
【Django】ログイン機能の実現方法(クラスベースビュー編)また、ユーザーのカスタマイズの仕方についても下記ページで解説していますので、User
を使わずに独自のカスタムユーザーを利用してアプリ開発を行いたい場合は参考にしてください!