#はじめに
本記事は、Djnagoで、ログイン機能を実装した際の備忘録として書いたものである。
今回は、Classで定義した内容に対して、ログイン制限をおこなう手法を記載いたします。
#前提条件
- OS環境は、Virtualboxで稼働中のCentOS8.1です。以下、OS詳細情報となります。
# cat /etc/centos-release
CentOS Linux release 8.1.1911 (Core)
-
Virtualboxのネットワーク設定は、「NAT」「ホストオンリーアダプター」で構成。
-
Django環境が構築済みであること。
※Django環境の構築は、以下を参照してください。
①Django 環境構築
②Django 環境設定&管理者サイト表示
④Django デザイン設定
⑤Django ログイン機能の実装
#(1)ログイン制御なしの状態での動作確認
##(1.1)DB側の環境設定
▼アプリケーション「book」を生成
# python manage.py startapp book
▼アプリをDjango全体の設定ファイルに定義
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrap4',
'accounts.apps.AccountsConfig',
]
↓
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrap4',
'accounts.apps.AccountsConfig'
'book.apps.BookConfig',#NEW
'django.contrib.humanize',#NEW
]
※「'django.contrib.humanize'」は、システムが表示する情報を人間は見やすいように変換してくれる機能
例)
・数値を3桁単位で、自動でカンマ区切りにしてくれる機能
・時刻表示を、「何分前」や「何日前」といった「日付/時刻データ」を元のデータと比較して、編集履歴などをわかりやすく表示する機能。
▼models.pyを定義
from django.db import models
from django.utils import timezone
class Category(models.Model):
name = models.CharField('カテゴリ名', max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
name = models.CharField('ブック名', max_length=100)
category = models.ForeignKey(Category, on_delete=models.PROTECT, verbose_name='カテゴリ')
text = models.TextField('感想', blank=True)
created_at = models.DateTimeField('作成日', default=timezone.now)
updated_at = models.DateTimeField('更新日', default=timezone.now)
def __str__(self):
return self.name
▼SQL文を生成
# python manage.py makemigrations book
▼実行するSQL文を確認
# python manage.py sqlmigrate book 0001
↓以下出力結果
BEGIN;
--
-- Create model Category
--
CREATE TABLE "book_category" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL);
--
-- Create model Book
--
CREATE TABLE "book_book" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "text" text NOT NULL, "created_at" timestamp with time zone NOT NULL, "updated_at" timestamp with time zone NOT NULL, "category_id" integer NOT NULL);
ALTER TABLE "book_book" ADD CONSTRAINT "book_book_category_id_616006cd_fk_book_category_id" FOREIGN KEY ("category_id") REFERENCES "book_category" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "book_book_category_id_616006cd" ON "book_book" ("category_id");
COMMIT;
「 python manage.py sqlmigrate アプリ名 マイグレーションID」で、migrateコマンドで実行するSQL分の確認をすることができる。
今回は、初回のマイグレーションなので、マイグレーションIDは0001を指定しているが、環境によってマイグレーションIDは変化する。
▼マイグレーションの実行状況を確認
# python manage.py showmigrations
↓以下出力結果
accounts
(no migrations)
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
book
[ ] 0001_initial
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initial
※「showmigrations」コマンドで、マイグレーションの実施の有無を確認することができる。
▼マイグレーションを実施
# python manage.py migrate
※migrateコマンドで、自動的に必要なテーブルデータなどを生成してくれる。
##(1.2)WEB側の環境構築
▼views.pyを修正
from django.views import generic
from .models import Book
class BookList(generic.ListView):
model = Book
▼Django全体のルーティングを設定
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app.urls')),
path('accounts/', include('django.contrib.auth.urls'))
path('book/', include('book.urls')),
]
▼アプリ側のルーティングを設定
from django.urls import path
from . import views
urlpatterns = [
path('', views.BookList.as_view(), name='book'),
]
▼NoteのTemplatesディレクトリを作成
# mkdir templates/book
▼ブックデータの一覧を表示するHTMLを生成
{% extends '../base.html' %}
{% load humanize %}
{% block content %}
<h1>ブック一覧</h1>
<table class='table table-striped table-hover'>
<tr>
<th>カテゴリー</th><th>本のタイトル</th><th>感想</th><th>更新日時</th>
</tr>
{% for book in object_list %}
<tr>
<td>{{ book.category }}</td>
<td>{{ book.name }}</td>
<td>{{ book.text }}</td>
<td>
<p class="date">{{ book.created_at }}
(
<time class="updated_at" datetime="{{ book.updated_at | date:'Y-m-d' }}">{{ book.updated_at | naturaltime }}に更新
</time>
)
</p>
</td>
</tr>
{% endfor %}
</table>
{% endblock %}
▼admin.pyを定義
from django.contrib import admin
from .models import *
admin.site.register(Book)
admin.site.register(Category)
##(1.3)動作確認
# python manage.py runserver 192.168.56.201:8000
▼以下のURLにアクセスし、テストデータを作成する。
※今回は、テストデータは管理者サイトで生成する前提で書いてます。
※キャプチャを参照。
http://192.168.56.201:8000/admin
▼以下のURLにアクセスし、きちんとデータが表示されているかを確認。
http://192.168.56.201:8000/book
※正常にデータが表示されていればOK
※私の環境では、こんな感じです。
#(2)ログイン制御ありの状態での動作確認
▼views.pyを修正
from django.views import generic
from .models import Book
from django.contrib.auth.mixins import LoginRequiredMixin
class BookList(LoginRequiredMixin, generic.ListView):
model = Book
※「LoginRequiredMixin」をインポートし、それをクラスに継承するだけで、ログインしたユーザのみのページを表示が可能になる。
詳細については、これを参照しいてください。
▼動作確認
# python manage.py runserver 192.168.56.201:8000
以下のURLにアクセスする。
http://192.168.56.201:8000/book
★以下項目と同じように、想定通りに動作すればOK!!
- 「http://192.168.56.201:8000/book」にアクセス後、ログイン画面に遷移する
- ログイン認証を実施後、「http://192.168.56.201:8000/book」にリダイレクトされる。
これでおけまるです(・ω・)ノ
#参考URL一覧
Django ListViewでモデルの一覧表示
Using the Django authentication system
Djangoテンプレート表示形式のカスタマイズ方法
Djangoで、ブログを作るシリーズ②