トップページの作成とログイン機能の追加
はじめに
今回はトップページの作成とログイン機能、ログアウト機能を実装します。
トップページの作成
トップページを作るにあたってrenderについて確認します。
Djangoではrequestオブジェクトを受け取ってresponseオブジェクトを返します。このときのresponseオブジェクトの作成にrender関数を使います。
では、book/urls.pyに以下の記述をします。
from django.urls import path from . import views urlpatterns = [ path('', views.index_view, name='index'), path('book/', views.ListBookView.as_view(), name='list-book'), path('book/<int:pk>/detail/', views.ListBookView.as_view(), name='detail-book'), path('book/create/', views.CreateBookView.as_view(), name='create-book'), path('book/<int:pk>/delete/', views.DeleteBookView.as_view(), name='delete-book'), path('book/<int:pk>/update/', views.UpdateBookView.as_view(), name='update-book'), ]
次にbook/views.pyに以下の記述をします。
from django.shortcuts import render from django.urls import reverse_lazy from django.views.generic import (ListView, DetailView, CreateView, DeleteView, UpdateView, ) from .models import Book # Create your views here. def index_view(request): return render(request, 'book/index.html',{'somedata':100}) class ListBookView(ListView): template_name = 'book/book_list.html' model = Book class DetailBookView(DetailView): template_name = 'book/book_detail.html' model = Book class CreateBookView(CreateView): template_name = 'book/book_create.html' model = Book fields = {'title', 'text', 'category'} success_url = reverse_lazy('list-book') class DeleteBookView(DeleteView): template_name = 'book/book_confirm_delete.html' model = Book success_url = reverse_lazy('list-book')
ここで追加した
def index_view(request): return render(request, 'book/index.html',{'somedata':100})
について、返り値の第一引数のrequestは必ず入れます。次の第二引数はファイルを指定します。第三引数はデータを指定します。今回は100を表示させます。左のsomedataは辞書のキーの部分で、右の100はバリューです。
ここからはindex.htmlを用いてブラウザ上データを表示させます。まず、index.htmlを新規作成します。
touch book/templates/book/index.html
作成した、book/templates/book/index.htmlに以下を記述します。
{{ somedata }} ||> この、somedataは先程述べたようにviews.pyのrender関数で設定したキーを表しており、ブラウザ上での出力は100となります。 ここまではfunction-based viewの流れについて作成していましたが、ここからはviewとModelを連携させます。 book/views.pyのindex_view関数を以下のように変更します。 >|python| def index_view(request): object_list = Book.objects.all() return render(request, 'book/index.html',{'object_list': object_list})
新たにobject_listを設定しました。これは、.allとなっているように、Bookテーブルにある全てのobjectsを表しています。
また、キーとバリューのところもobject_listという名前で呼び出せるようにしました。
更に、Book.objects.all()のall()の部分をorder_by('catefgory')やorder_by('title')とするとカテゴリーやタイトル順で一覧の並び替えができます。
views.pyの記述が終われば、book/templates/book/index.htmlを以下のように変更します。
{% extends 'base.html' %} {% block title %}書籍一覧{% endblock %} {% block h1 %}書籍一覧{% endblock %} {% block content %} {% for item in object_list %} <div class="p-4 m-4 bg-light border border-success rounded"> <h2 class="text-success">{{ item.title }}</h2> <h6>カテゴリー: {{ item.category }}</h6> <div class="mt-3"> <a href="{% url 'detail-book' item.pk %}">詳細へ</a> </div> </div> {% endfor %} {% endblock content %}
これでサーバーを立ち上げ、127.0.0.1:8000/にアクセスします。前回127.0.0.1:8000/book/にあったページがトップページとして表示されます。
ログイン、ログアウト機能の追加
ログイン機能
ログイン機能の実装には、フォームに入力されたユーザー名とパスワードがデータベースにあるユーザーの情報と一致しているかを照合し、一致しているユーザーのみログインさせる必要があります。
ログイン機能はDjangoでサポートされている認証のViewを呼び出すことで使えます。呼び出しにはauthアプリケーションのurls.pyを呼び出します。
呼び出すためにbookproject/urls.pyに以下を記述します。
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('accounts/', include('accounts.urls')), path('', include('book.urls')), ]
これによりaccounts/というurlをrequestすることでauthアプリケーションのurls.pyを呼び出すことができます。
ここまででログイン機能のやり方はできましたが、ログイン画面のviewは作っていません。これは127.0.0.1:8000/accounts/login/にアクセスすると呼び出されるviewになります。
ログイン画面のviewを以下のように作成します。
mkdir temprates/registration touch templates/registration/login.html
作成したtemplates/registration/login.htmlに以下の記述をします。
{% extends 'base.html' %} {% block content %} <h1>ログイン</h1> <form method="post" class="p-4 m-4 bg-light border border-success rounded form-group"> {% csrf_token %} {% for error in form.errors.values %} {{ error }} {% endfor %} <label> ユーザ ID </label> <input class="form-control" name="username"> <label> パスワード </label> <input type="password" class="form-control" name="password"> <button type="password" class="btn btn-success mt-4">ログインする</button> </form> {% endblock %}
これでサーバーを立ち上げ127.0.0.1:8000/accounts/login/にアクセスします。すると以下のような画面が表示されます。
ただ、ログインしようとするとエラーがでます。
ログインするとaccounts/profile/というurlにアクセスするような設定になっているのに、urlの設定をしていないのでエラーがでました。
解決のためにbookproject/setting.pyに以下の記述を追加します。
LOGIN_REDIRECT_URL = 'list-book'
これでログインすると書籍一覧のページが表示されます。
ログアウト機能
まずはbook/urls.pyに以下の記述をします。
from django.urls import path from . import views urlpatterns = [ path('', views.index_view, name='index'), path('book/', views.ListBookView.as_view(), name='list-book'), path('book/<int:pk>/detail/', views.ListBookView.as_view(), name='detail-book'), path('book/create/', views.CreateBookView.as_view(), name='create-book'), path('book/<int:pk>/delete/', views.DeleteBookView.as_view(), name='delete-book'), path('book/<int:pk>/update/', views.UpdateBookView.as_view(), name='update-book'), path('logout/', views.logout_view, name='logout'), # 追加 ]
また、book/views.pyにも以下の記述をします。
from django.shortcuts import render, redirect from django.contrib.auth import logout from django.urls import reverse_lazy from django.views.generic import (ListView, DetailView, CreateView, DeleteView, UpdateView, ) from .models import Book # Create your views here. def index_view(request): object_list = Book.objects.order_by('category') return render(request, 'book/index.html',{'object_list': object_list}) def logout_view(request): logout(request) return redirect('index') class ListBookView(ListView): template_name = 'book/book_list.html' model = Book class DetailBookView(DetailView): template_name = 'book/book_detail.html' model = Book class CreateBookView(CreateView): template_name = 'book/book_create.html' model = Book fields = {'title', 'text', 'category'} success_url = reverse_lazy('list-book') class DeleteBookView(DeleteView): template_name = 'book/book_confirm_delete.html' model = Book success_url = reverse_lazy('list-book') class UpdateBookView(UpdateView): template_name = 'book/book_update.html' model = Book fields = {'title', 'text', 'category'} success_url = reverse_lazy('list-book')
これでサーバーを立ち上げ、127.0.0.1:8000/logout/にアクセスします。アクセスするとトップページが表示され、ログアウトできているかの確認には管理画面にアクセスします。ユーザー名とパスワードを求められたらログアウトできています。
つぎにトップページにログイン、ログアウトするためのリンクを付けます。リンクはbase.htmlで作成したnavbarに追加します。
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Bootstrap CSS --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <title>{% block title %}{% endblock title %}| 本棚アプリケーション</title> </head> <body> <nav class="navbar navbar-dark bg-success sticky-top"> <div class="navbar-nav d-flex flex-row"> <a class="nav-link mx-3" href="{% url 'list-book' %}">書籍一覧</a> <a class="nav-link mx-3" href="{% url 'create-book' %}">書籍登録</a> </div> <div class="navbar-nav d-flex flex-row"> {% if request.user.is_authenticated %} <a class="nav-link mx-3 href={% url 'logout' %}">ログアウト</a> {% else %} <a class="nav-link mx-3 href={% url 'login' %}">ログイン</a> {% endif %} </div> </nav> <div class='p-4'> <h1>{% block h1 %}{% endblock %}</h1> {% block content %}{% endblock content %} </div> </body> </html>
新たに追加した、{% if request.user.is_authenticated %}はユーザーがログイン状態かを判定しています。
おわりに
今回は本棚アプリケーションのトップページとログイン、ログアウト機能を追加しました。
はじめの方に登録したユーザー名とパスワードを使ってログイン、ログアウトをするのはアプリケーションを作る上で大切です。