#はじめに
ログイン・ログアウト機能を実装したので、その際に調べた内容を備忘録として投稿します。
どなたかの役に立てば幸いです。
記事を作成した後に確認したのですが、結構雑に記載してしまったので、
よくわからない箇所があったら各自調べてください・・・。すみません。。
##実装
プロジェクトの作成からログイン・ログアウト機能の実装まで全て記載していきます。
###プロジェクト作成
login_sample_2というプロジェクトを作成していますが、
別にここの箇所はなんでもいいです。
ついでにcdでディレクトリを移動しておきます。
$ django-admin startproject login_sample_2
$ cd login_sample_2/
###アプリケーションの作成
今回はaccount
というアプリケーションを作成します。
アプリケーション名もなんでも良いです。
$ python manage.py startapp account
###settings.pyの修正
settings.py
に必要なもの修正していきます。
先程作成したアプリケーションと、
ログインとログアウトに関わるDjangoの基本設定を行います。
後は言語やタイムゾーンも変更しておきましょう。
INSTALLED_APPS = [
'account', ### 追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
# LANGUAGE_CODE = 'en-us' ### 修正前
LANGUAGE_CODE = 'ja' ### 修正後
# TIME_ZONE = 'UTC' ### 修正前
TIME_ZONE = 'Asia/Tokyo' ### 修正後
LOGIN_URL = "account:login" ### 追加
LOGIN_REDIRECT_URL = "account:home" ### 追加
LOGOUT_REDIRECT_URL = "account:top" ### 追加
パラメータ | 説明 |
---|---|
LOGIN_URL | ログインが必要な画面にログインしていないユーザがアクセスした際に自動的にリダイレクトされるページ |
LOGIN_REDIRECT_URL | ログイン後に自動的にリダイレクトされるページ |
LOGOUT_REDIRECT_URL | ログアウト後に自動的にリダイレクトされるページ |
先頭についているaccount:
は、
urls.pyに記載されているapp_name
の値がaccount
の
urlpatternsを参照するように指定しています。
###forms.pyの作成
ログイン画面のフォームを作成します。
今回は、Djangoに標準で用意されているAuthenticationFormというクラスを利用します。
AuthenticationFormクラスには標準でユーザ名とパスワードのフォームが定義されているため、
簡単にユーザ名とパスワードで認証する画面フォームを作成できます。
まず、account配下にforms.py
というファイルを作成します。
forms.pyの中身を下記のように記述します。
from django.contrib.auth.forms import AuthenticationForm
class LoginForm(AuthenticationForm):
"""ログインフォーム"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs["class"] = "form-control"
###views.pyの修正
views.py
を以下の通りに修正します。
最初に表示するトップ画面と、ログイン後に表示するホーム画面、
Django標準クラスのLoginViewと、LogoutViewを継承したクラスを作成します。
また、LogoutViewの方には、LoginRequiredMixinも継承します。
LoginRequiredMixinを継承すると、Loginしたユーザのみ閲覧できるようになります。
ログインしていないユーザが閲覧しようとすると、
settigns.pyで定義したLOGIN_URLにリダイレクトします。
また、LogoutViewのtemplate_name
は、
ログアウト後に表示するページを渡しています。
from django.contrib.auth.views import LoginView, LogoutView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
from . import forms
class TopView(TemplateView):
template_name = "account/top.html"
class HomeView(LoginRequiredMixin, TemplateView):
template_name = "account/home.html"
class LiginView(LoginView):
"""ログインページ"""
form_class = forms.LoginForm
template_name = "account/login.html"
class LogoutView(LoginRequiredMixin, LogoutView):
"""ログアウトページ"""
template_name = "account/login.html"
###urls.pyの修正
次にurls.pyの修正を行います。
まず先にプロジェクトフォルダ配下のurls.pyです。
from django.contrib import admin
from django.urls import path, include ### include追加
urlpatterns = [
path('admin/', admin.site.urls),
path("", include("account.urls")), ### 追加
]
path("", include("account.urls"))
を追記することにより、
http://127.0.0.1:8000/
にアクセスした際にaccount.urls
を参照するようになります。
path("account/", include("account.urls"))
などにすれば、
http://127.0.0.1:8000/account/
にアクセスした際に参照するようになります。
次に、アプリケーション配下のurls.pyを作成します。
初期状態ではファイルが存在しないので、ファイル作成をしてから記載します。
from django.conf.urls import url
from django.urls import path
from . import views
app_name="account"
urlpatterns = [
path("", views.TopView.as_view(), name="top"),
path("home/", views.HomeView.as_view(), name="home"),
path("login/", views.LoginView.as_view(), name="login"),
path("logout/", views.LogoutView.as_view(), name="logout"),
]
path("login/", views.LoginView.as_view(), name="login")
により、
http://127.0.0.1:8000/login
にアクセスするとログイン画面が表示されるようになります。
###テンプレートファイルの作成
次に表示するテンプレートファイルの作成です。
アプリケーション配下にtemplatesフォルダを作成し、さらにその配下に
アプリケーション名と同じaccount
フォルダを作成します。
accountフォルダ配下に以下の4つのファイルを作成します。
・base.html
・home.html
・top.html
・login.html
構造は下記のようになっていると思います。
$ tree
├── account
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── models.py
│ ├── templates
│ │ └── account
│ │ ├── base.html
│ │ ├── home.html
│ │ └── top.html
│ │ └── login.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
では各ファイルを修正していきます。
まずはベースとなるbase.html
から。
Bootstrap4のスタータテンプレートをコピペしています。
Bootstrapを利用すると簡単に綺麗なデザインでWebサイトを組めるので
ぜひ学習してみてください。
{% block title %}{% endblock %}
と
{% block content %}{% endblock %}
の箇所は
Django特有の記述方法である、タグ機能です。
これについては後ほど説明します。
<!doctype html>
<html lang="ja">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>{% block title %}{% endblock %}</title> ### 修正
</head>
<body>
{% block content %}{% endblock %} ### 修正
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
これをベースにして他のファイルの作成を行います。
次にtop.html
です。
ここではログイン画面に行くためのリンク記述しておきます。
{% extends "account/base.html" %}
により、
base.htmlの内容を引き継ぐことができます。
そして、base.htmlにて記載のあった{% block **** %}{% endblock %}
ですが、
top.htmlでも似たものが登場します。
これは、base.htmlの{% block %}で囲まれている箇所と紐づけているようなイメージです。
{% extends "account/base.html" %}
{% block title %}トップ{% endblock %}
{% block content %}
<div class="container">
<h1 class="my-5">Top画面</h1>
<a href="{% url 'account:login' %}" class="btn btn-outline-primary">ログイン</a>
</div>
{% endblock %}
base.htmlを1行目のextendsタグ
で継承していることにより
top.htmlの内容はとても簡単に見えますが、
もし継承していない状態だったら下記のようになります。
<!doctype html>
<html lang="ja">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<title>トップ</title>
</head>
<body>
<div class="container">
<h1 class="my-5">Top画面</h1>
<a href="{% url 'account:login' %}" class="btn btn-outline-primary">ログイン</a>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>
titleとbody内は各htmlで異なるので、blockタグで囲んで各ファイルで変更可能にしています。
また、aタグの{% url 'account:login' %}
ですが、
app_nameがaccountになっているurlpatternsの中からname="login"のものを探しています。
次にlogin.html
の内容を記述します。
例のごとくextends
でbase.htmlを継承。
フォームを作成する際にはformタグで囲んだ中に色々記述します。
{% csrf_token %}
はアプリの脆弱性対策のために記載します。必須です。
{% for field in form %}{% endfor %}
内で
色々表示しています。
{% extends "account/base.html" %}
{% block title %}ログイン{% endblock %}
{% block content %}
<div class="container">
<h1>ログイン</h1>
<form action="" method="POST">
{% csrf_token %}
{{ form.non_field_errors }}
{% for field in form %}
{{ field.label }}
<br>
{{ field }}
<br>
{{ field.error }}
{% endfor %}
<br>
<button type="submit">ログイン</button>
</form>
</div>
{% endblock %}
ログイン後はsettings.pyで記述した、
LOGIN_REDIRECT_URLにリダイレクトされます。
今回はaccount:home
になります。
続いてhome.html
の内容を記述していきます。
{{ user.username }}
はログインしているユーザの名前を取得しています。
{% extends "account/base.html" %}
{% block title %}ホーム{% endblock %}
{% block content %}
<div class="container">
<h1 class="my-5"></h1>
<p>{{ user.username }}さん、こんにちは。</p>
<a href="{% url 'account:logout' %}">ログアウト</a>
</div>
{% endblock %}
ログアウトは、{% url 'account:logout' %}
でOKです。
ここまでできたら、コンソールを操作します。
下記の3つを実行してください。
createsuperuser
では管理者ユーザを作成します。
任意のユーザ名とパスワードを入力してください。
メールアドレスは入力しなくても大丈夫です。
$ python manage.py migrate
$ python manage.py createsuperuser
$ python manage.py runserver
サーバを起動したら、http://127.0.0.1:8000
にアクセスします。
(ちなみに、ログインボタンが少しかっこいいのはBootstrapで設定したからです。
top.htmlのclass="btn btn-outline-primary"
の箇所です。)
ログインボタンを押すと、次の画面にいきました。
URLはhttp://127.0.0.1:8000/login
になってますね。
ここで先程createsuperuserで作成した情報を入力しましょう。
http://127.0.0.1:8000/home
に遷移しました。
adminという名前でユーザを作成したので、「adminさん、こんにちは」と表示されます。
ログアウトを押すと、top画面に戻ることを確認しましょう。
戻った後に、URLにhttp://127.0.0.1:8000/home
と入力して、
ログインしていない状態でホーム画面にアクセスしてみます。
いきなりホーム画面には行けずログイン画面が表示されています!
URLもhttp://127.0.0.1:8000/login/?next=/home/
になっています。
こんな感じですかね!
#さいごに
最後までご覧いただきありがとうございました。
記事の作成中にミスに気づいて結構訂正したのですが、
その名残で一部おかしいところあるかもです。。。
もし何か記載ミスがあったらご連絡ください!