見出し画像

【79日目】Django_ログイン画面の作成方法_プログラミング学び日記

 このnoteは、31歳未経験からエンジニアを目指して勉強していく記録を綴っているものです。現在はAdTechでカスタマーサクセスを担当しつつ、色んなチャンスに恵まれ、CS業務や子育てと並行しながらチャレンジしています。

 これからプログラミングを始める方にとってのTipsやモチベアップに繋げられるように頑張りたいと思っています。
--------------------------------------------

昨晩から子供が入院することになりました。
恐らくウイルス性胃腸炎から来るもので、嘔吐が続いたことによって脱水症状気味になっていたそうです。

昨日は入院準備に追われましたが、今日はやれることがないので仕事も勉強もいつも通りでした。全然集中できる状況ではありませんが。。


以下の動画から学んだことを中心にアウトプットします。


ログインのどんな機能を実装する?

以下のような画面が出来上がります。ログイン、パスワード変更、パスワード再設定、ログアウトができる機能です(この4つはDjangoに準備されていて簡単に実装できます)。

パスワード再設定は登録したアドレスにメールが届いて、正しいユーザーからのアクセスがどうかバリデーションのうえ、パスワード変更ができるようになっています。

ログイン画面
ログイン後のトップページ
パスワード変更画面

では順番に見ていきます。


Djangoでは簡単にログイン機能が実装可能になっている

まず前提として、Djangoにはそもそもログイン機能を実装するための準備が整っています。開発者はそれをカスタマイズするだけOKな半面、例えばテンプレート名などはDjangoが用意している名前と1文字でも違ったらエラーがおきます。


全体設定にアプリを追加

これ自体はアプリを作る際にいつも踏む手順ですが、いつもと違うのは、INSTALLED_APPSの最初にアプリ名を書き込むという点です。

以下のregistrationが今回のアプリ名です。

INSTALLED_APPS = [
    'registration', 
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

これは、Djangoは上から順に処理していく関係で、「admin」アプリより上に記載しないと、ログイン画面が「admin」に用意されているものになってしまうためです。

せっかくアプリをかっこよく作っても表示されなくなってしまうので、ログイン機能用のアプリは上に記載します。


URLをいろいろ設定_urls.py

全体設定のurls.pyとsettings.pyを編集します。これまではアプリの中にurls.pyを作成することが多かったですが、今回は単純なアプリなので、全体設定のurls.pyに記載しています。

また、今回はviewもurls.pyに1行で記載してしまっています。viewの内容がテンプレートを表示させるだけなので、こちらにまとめてしまっていいみたいです。

また、login_requiredとdjango.contrib.auth.urlsはログイン特有のものです。前者は引数に渡したviewがログインしないと見れないようになるもので、後者はログインに必要な機能のurlが格納された箱のようなものです。

[urls.py]
 
from django.contrib import admin
from django.urls import path, include
from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView


# TemplateViewは今までviews.pyにちゃんとコードを書いて作っていたが、テンプレートを一つ表示するだけなら以下でOK
index_view = TemplateView.as_view(template_name="registration/index.html")

urlpatterns = [
    path('admin/', admin.site.urls),
    # index_viewはログインしないと見れない
    path("", login_required(index_view), name="index"),
    # もしもdjangoが元々用意しているurlにマッチしたらそっちを表示する、という意味
    # マッチしなければトップページを表示する(index_view)
    # ここの「urls」の中には、ログイン、ログアウト、パスワード変更、パスワードリセット等が含まれている
    path('', include("django.contrib.auth.urls")),
]


URLをいろいろ設定_settings.py

settings.pyの最後のほうに以下のコードを書き込みます。ログインやログアウト、パスワード再設定の時の挙動を定義しています。

パスワード再設定はメールで行う想定ですが、今回は開発用の環境を整えるにとどめています。メールサーバーを連携させるのは更にひと手間かかるみたいです。

各コードの詳細はコメントアウトして書き込みました。

[settings.py] 

# console.EmailBackendというのを指定すると、メールサーバーの面倒な設定をしなくても、ターミナルにメールの本文を出力してくれる
# メールを送らなくてもメールをテストできるため開発中は便利
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

# ログインが必要なページにログインせずにアクセスしたとき、そのユーザーをどのページに飛ばすかという設定
LOGIN_URL = "/login/"

# ログインに成功したときにユーザーをどのページに移動させるかという設定
LOGIN_REDIRECT_URL = "/"

# ログアウトしたときにユーザーをどのページに移動させるかという設定
LOGOUT_REDIRECT_URL = "/login/"

また、本番環境ではパスワード再設定用に必ず以下の2行を設定します。これを入れることで、送られてくるulrがHTTPではなくHTTPSになります。

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SECURE_SSL_REDIRECT = True

HTTPSはWebサイトの安全性を確保するための仕組みで、Webページの表示に使われるHTTPの通信において、暗号化方式であるSSL/TLSを利用する方法を指します。具体的には盗聴防止(暗号化通信)、改ざん防止、なりすまし防止などが期待できます。


テンプレートを作成する際の工夫

細かいテンプレート作成が多いので、できるだけ省力化します。「base.html」や「_form.html」などのファイル名で使いまわし用htmlを作ればOKです。

今回はボタンに表示する文字を変数にする(submit_labelとした)ことで、ログインやパスワード変更などの画面で同じフォーマットを使いまわせるようにしています。

また、_fomr.htmlはログイン関係のテンプレート用フォーマットなので、「form.as_p」でフォームを表示させています。これは何かというと、ログイン関係のulrに飛ぶとき、ログインならログイン用の、パスワード変更なら変更用のフォームが「form」という名前で一緒に送信されてきており、それを表示させています。

ここまで標準機能として搭載してくれているのでDjangoはすごいですよね。おかげ最小限のコードで機能が実装できます。

[_form.html]
 
<!--ボタン名を変数にしていることで、このテンプレートをパスワード変更や登録のフォームで使いまわせるようにしている-->
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="{{ submit_label }}" />
</form>
[login.html] 

{% extends "base.html" %}
{% block main %}
<h2>ログイン</h2>
{% include "_form.html" with submit_label="ログイン" %}
{% endblock %}

上の2つのコードの組み合わせ(とextendsしているbase.html)で、記事の冒頭にあるログイン画面が表示されます。formという名前で、ユーザー名とパスワードのフォームが送信されてきている形ですね。


各テンプレートの作成

ログイン画面のテンプレートは次の手順で作成します。templatesディレクトリ直下に「registration」ディレクトリを作成し、その直下に以下の名前で各テンプレートを作成します。

index.htmlは手動で設定したものですが、それ以外の全てのファイルは以下のファイル名でないとDjangoが見つけられません(エラーになる)。1文字でも違ったらだめです。

ログイン関連のテンプレートファイル一覧

各ファイルの中身はほとんどlogin.htmlと似たような感じです。

ただ、パスワード再設定のみ少し工夫が必要で、バリデーション機能をつける必要があります。


パスワードを忘れた際の再設定メール

ログインしていない状態の人にパスワードの再設定を許す機能なので、しっかりバリデーションする必要があります。

で、実はそのバリデーション自体はDjangoが裏側でやってくれています。「validlink」という変数に、TrueなのかFalseなのかが自動で代入されているのです。そのためTrue(バリデーションOK)だった時の処理と、Falseだった時の処理を条件分岐しておくだけでOKです。

[password_reset_confirm.html]
 
{% extends "base.html" %}
{% block main %}
<h2>パスワード再設定</h2>

{% if validlink %}
    {% include "_form.html" with submit_label="変更" %}
{% else %}
    <p>無効なリンクです。</p>
{% endif %}

{% endblock %}

{% if validlink %} ~ {% endif %}までが条件分岐のコードです。


結構複雑でしたが何とか書き上げました。。
お読みいただきありがとうございました。


これまで修了したコース等

【YouTube_Django関係】
Pythonでウェブサービスを作ろう! #1
テンプレートをマスターしよう! #2
静的ファイルを配信しよう !#3
本番公開しよう! #4
データベースと接続しよう! #5
ブログを作って学ぶモデル入門! #6
これが汎用ビューの力! #7
Djangoフォームを自由自在に操ろう! #8
djagoを最大限使って効率よくログインを作ろう! #9
データベースマイグレーション前編 #15
データベースマイグレーション後編 #16

【Paiza】
Aランクレベルアップメニュー 24/49問
データセット選択メニュー 4/17問
配列メニュー      59/64問
ループメニュー1 20/20問
ループメニュー2 12/20問
条件分岐メニュー    25/25問
二重ループメニュー   19/19問
配列活用メニュー    26/26問
文字列処理メニュー   30/30問
Bランクレベルアップメニュー 62/62問
Cランクレベルアップメニュー 30/30問
ランクB合格
ランクC合格

【書籍/ブログ】
Django入門 | 初心者でも1時間でWebアプリ(Todoアプリ)を作成するコース
基礎からのMySQL     514/514頁
Web技術の基本      189/189頁 ※2周目中
京大のPython教科書    116/201頁
Pythonデータベースプログラミング 194/194頁
Pythonエンジニアファーストブック読了

【Progate】
Python Ⅰ~Ⅴ
Python アプリ版 コースⅠ~Ⅴ
SQL Ⅰ~ Ⅳ
SQL アプリ版 コースⅢ
HTML&CSS 初級編

【その他】
Pythonの環境構築
VSCodeの環境構築
MySQLの環境構築(MAMP)
Git / GitHubの環境構築
HEROKUの環境構築

この記事が気に入ったらサポートをしてみませんか?