※はじめからはこちら
第2回目ではログイン処理を作っていきます。Djangoは実はデフォルトでログイン周りの機能が実装されています。http://localhost:3000/admin
で表示される管理画面用と同じものが利用できます。
しかし、せっかくなのでデザイン等を少しいじりたいと思います。
初期ユーザの作成
ログイン周りを作っていく上では、ユーザがあると便利なので先に作ってしまいます。ユーザ名は何でもいいですが、とりあえずtest
としてパスワードもtest
としています。
$ docker-compose exec service python manage.py createsuperuser
WARNING: The DJANGO_ENV variable is not set. Defaulting to a blank string.
Username (leave blank to use 'root'): test ★入力
Email address:
Password: ★見えないが、testと入力
Password (again): ★見えないが、testと入力
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y ★y
Superuser created successfully.
ユーザ名と、2度のパスワード入力をしてそれ以外はEnterでSKIPすると、パスワードが短いが良いか?と聞かれるのでyを入力してユーザの作成が完了します。
念の為以下にアクセスしtest/testでログインできるかは確認しておきましょう。
![Site_administration___Django_site_admin_と_Franz.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F44722%2F5bb54062-34c3-419f-db32-835945d45ba4.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=48690b41095cdb6f86217810f4bcf2ce)
管理画面に入れるようになっているはずです。
ホーム画面のログイン必須化
今はhttp://localhost:3000
にログインせずにアクセスできるようになっていますが、こちらをログイン必須にしましょう。
Djangoではlogin_required
という関数が用意されており、これを利用すると簡単に特定URLへのアクセスをログイン必須にすることができます。
また、認証周りのロジックに割り当てるURLも指定しておきます。
@@ -1,13 +1,15 @@
from django.conf import settings
from django.conf.urls.static import static
+from django.contrib.auth.decorators import login_required
from django.contrib import admin
-from django.urls import path, re_path
+from django.urls import path, re_path, include
from django.views.generic import TemplateView
urlpatterns = [
+ path('accounts/', include('django.contrib.auth.urls')),
path('admin/', admin.site.urls),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
# app routing to vue-router
-urlpatterns += [re_path('.*', TemplateView.as_view(template_name='index.html'))]
+urlpatterns += [re_path('.*', login_required(TemplateView.as_view(template_name='index.html')))]
もし、先程の管理画面にログインしたままであれば一旦右上のLOGOUTをクリックしてログアウトした上でhttp://localhost:3000/
にアクセスしてみましょう。
![TemplateDoesNotExist_at__accounts_login_.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F44722%2F5abd277f-83e5-7742-255a-db39f43c0cd2.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=4c0f97df3cc5586324a697acb4d66c61)
registration/login.html
というファイルが見つからないというエラーになります。これはログイン画面にリダイレクトしたものの、そこで使用するテンプレートがないため表示できなかったことを意味しています。では、ないと言われたファイルを作りましょう。
templateの作成
以下のファイルを作成します。
{% extends "base.html" %}
{% block title %}LOGIN{% endblock %}
{% block body %}
<div class="container py-5">
<div class="row">
<div class="col-md-12">
<h2 class="text-center mb-4">The KANBAN</h2>
<div class="row">
<div class="col-md-6 mx-auto">
<div class="card rounded-0">
<div class="card-header">
<h3 class="mb-0">Login</h3>
</div>
<div class="card-body">
{% if form.errors %}
<div class="alert alert-danger" role="alert">Your username and password didn't match. Please try again.</div>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% endif %}
{% endif %}
<p>Please login to see this page. (or <a href="/accounts/signup/">signup</a>)</p>
<form class="form" role="form" autocomplete="off" id="formLogin" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
<label for="uname1">Username</label>
<input type="text" class="form-control form-control-lg rounded-0" name="username" id="username"
required="">
<div class="invalid-feedback">Oops, you missed this one.</div>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control form-control-lg rounded-0" id="password"
name="password"
required=""
autocomplete="new-password">
<div class="invalid-feedback">Enter your password too!</div>
</div>
<button type="submit" class="btn btn-success btn-lg float-right" id="btnLogin">Login</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
結構込み入ったHTMLですが、おしゃれなログイン画面をBootstrap4で作ろうと思った結果やむなしでした。ここは申し訳ないですがコピペでおねがいします。
また、ログイン周りの設定を少し入れておきます。
@@ -127,3 +127,8 @@ STATIC_ROOT = os.path.join(APP_ROOT_PATH, 'static')
# HTTPの起点を指定
ROOT_URLCONF = 'application.views.urls'
+
+# login related
+LOGIN_REDIRECT_URL = '/'
+LOGIN_URL = '/accounts/login/'
+LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL
はログイン完了後にデフォルトでどのページに飛ばすかの指定で、ここでは/
に飛ばすようにしています。また、LOGOUT_REDIRECT_URL
は逆にログアウト後にどこに飛ばすかです。
これらの変更をしてから再度http://localhost:3000
にアクセスすると、以下のようなログイン画面が出るはずです。
![LOGIN.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F44722%2Fdb853f47-3d18-6c46-bba7-0b85a8e0717d.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=c037b3ace815057250bc5cd7a3fc0709)
ここからtest/testでログインすればちゃんとログイン後の画面がでるようになります。
ユーザ作成の実装
さて、ちゃんとログインできるようになりましたがユーザを作成する画面がないのでtest以外のユーザがいません。これを実装していきましょう。
まずはデザインからつくっていきます。ほとんどLoginと同じものを作ります。
{% extends "base.html" %}
{% block title %}SIGNUP{% endblock %}
{% block body %}
<div class="container py-5">
<div class="row">
<div class="col-md-12">
<h2 class="text-center mb-4">SignUp Form</h2>
<div class="row">
<div class="col-md-6 mx-auto">
<div class="card rounded-0">
<div class="card-header">
<h3 class="mb-0">SignUp</h3>
</div>
<div class="card-body">
{% if form.errors %}
<div class="alert alert-danger" role="alert">{{ form.errors }}</div>
{% endif %}
{% if next %}
{% if user.is_authenticated %}
<p>Your account doesn't have access to this page. To proceed,
please login with an account that has access.</p>
{% endif %}
{% endif %}
<p>Please signup to see this page. (or <a href="/accounts/login/">login</a>)</p>
<form class="form" role="form" autocomplete="off" id="formLogin" method="post" action="{% url 'signup' %}">
{% csrf_token %}
<div class="form-group">
<label for="uname1">Username</label>
<input type="text" class="form-control form-control-lg rounded-0" name="username" id="username"
required="">
<div class="invalid-feedback">Oops, you missed this one.</div>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control form-control-lg rounded-0" id="password1"
name="password1"
required=""
autocomplete="new-password">
<div class="invalid-feedback">Enter your password too!</div>
</div>
<div class="form-group">
<label>Re Password</label>
<input type="password" class="form-control form-control-lg rounded-0" id="password2"
name="password2"
required=""
autocomplete="new-password">
<div class="invalid-feedback">Enter your password too!</div>
</div>
<button type="submit" class="btn btn-info btn-lg float-right" id="btnLogin">SignUp</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
ユーザ作成の機能は標準では用意されていないのでViewを自分で実装します。application/views/accounts/signup.py
としてファイルとして保存します。
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views import generic
class SignUpView(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'registration/signup.html'
generic.CreateView
はDjangoの機能で、あるモデル(データ)の作成を簡単にしてくれる関数です。form_class = UserCreationForm
で指定しているようにユーザの作成フォームをregistration/signup.html
で表示してくれます、
最後はこのViewとURLのマッピングを追加します。
from django.urls import path, re_path, include
from django.views.generic import TemplateView
+from .accounts import signup as signup_view
+
+
urlpatterns = [
+ path('accounts/signup/', signup_view.SignUpView.as_view(), name='signup'),
path('accounts/', include('django.contrib.auth.urls')),
path('admin/', admin.site.urls),
]
これで、http://localhost:3000/accounts/signup/
にアクセスすると以下のような画面が出ます。
![SIGNUP.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F44722%2F822b51e2-1abf-38f5-be78-d8bdedec4fb7.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=a3a2dbee9f8bc49842a366d4bc03dffb)
これでユーザ作成画面は完了です。
ついでに、ログイン画面側にもsignupへのリンクを貼っておきましょう。
</div>
<div class="card-body">
- <p>Please login to see this page.</p>
+ <p>Please login to see this page. (or <a href="/accounts/signup/">signup</a>)</p>
<form class="form" role="form" autocomplete="off" id="formLogin" method="post" action="{% url 'login' %}">
{% csrf_token %}
<div class="form-group">
これでログイン画面にsignupへのリンクがはられました。
![LOGIN.png](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.amazonaws.com%2F0%2F44722%2F87ac49b8-2df5-f3f8-8d4b-fc0e00cd15cd.png?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=c073a27cfdef04edef085fe096d2688d)
ログイン周りはこれで完了です。
次回