LoginSignup
11
10

More than 1 year has passed since last update.

【Django】ログイン・ログアウト機能の実装

Last updated at Posted at 2021-07-28

はじめに

ログイン・ログアウト機能を実装したので、その際に調べた内容を備忘録として投稿します。

どなたかの役に立てば幸いです。

記事を作成した後に確認したのですが、結構雑に記載してしまったので、
よくわからない箇所があったら各自調べてください・・・。すみません。。

実装

プロジェクトの作成からログイン・ログアウト機能の実装まで全て記載していきます。

プロジェクト作成

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の基本設定を行います。

後は言語やタイムゾーンも変更しておきましょう。

settings.py
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の中身を下記のように記述します。

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は、
ログアウト後に表示するページを渡しています。

views.py
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です。

login_sample_2/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を作成します。
初期状態ではファイルが存在しないので、ファイル作成をしてから記載します。

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特有の記述方法である、タグ機能です。

これについては後ほど説明します。

base.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>{% 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 %}で囲まれている箇所と紐づけているようなイメージです。

account/top.html
{% 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の内容はとても簡単に見えますが、
もし継承していない状態だったら下記のようになります。

account/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 %}内で
色々表示しています。

login.html
{% 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 }}はログインしているユーザの名前を取得しています。

home.py
{% 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にアクセスします。

こんな感じの画面が出てきましたかね?
スクリーンショット 2021-07-28 23.49.49.jpg

(ちなみに、ログインボタンが少しかっこいいのはBootstrapで設定したからです。
top.htmlのclass="btn btn-outline-primary"の箇所です。)

ログインボタンを押すと、次の画面にいきました。
URLはhttp://127.0.0.1:8000/loginになってますね。
スクリーンショット 2021-07-28 23.51.22.jpg

ここで先程createsuperuserで作成した情報を入力しましょう。

http://127.0.0.1:8000/homeに遷移しました。
スクリーンショット 2021-07-28 23.52.32.jpg

adminという名前でユーザを作成したので、「adminさん、こんにちは」と表示されます。
ログアウトを押すと、top画面に戻ることを確認しましょう。

戻った後に、URLにhttp://127.0.0.1:8000/homeと入力して、
ログインしていない状態でホーム画面にアクセスしてみます。

いきなりホーム画面には行けずログイン画面が表示されています!
URLもhttp://127.0.0.1:8000/login/?next=/home/になっています。
スクリーンショット 2021-07-28 23.54.31.jpg

こんな感じですかね!

さいごに

最後までご覧いただきありがとうございました。

記事の作成中にミスに気づいて結構訂正したのですが、
その名残で一部おかしいところあるかもです。。。

もし何か記載ミスがあったらご連絡ください!

11
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
10