DjangoはPython製のWebフレームワークです。Webアプリ開発でよく使われる「ユーザー認証」「管理画面」などの便利な機能があらかじめ含まれているので、仕様を理解して使えば簡単に掲示板のようなものを作成して公開することができます。ただ仕様を完全に理解するのは難しいです。
ではさっそく使ってみましょう。
作成した掲示板はこんな感じになります。 ⇒ 動作確認はこちらから
プロジェクトとアプリを作成する
まずDjangoがインストールされていないのであればインストールしましょう。
Djangoのインストールは非常に簡単で、ターミナル(WindowsならコマンドプロンプトまたはPowerShell)で以下のように入力するだけです。
1 |
$ pip install django |
1行目の「$」は、その後ろがターミナルに入力するコマンドであることを表しています。
インストールが終わったらプロジェクトとアプリを作成します。
プロジェクトを作成するときはプロジェクト名をmyappにするのであればプロジェクトを作成したいディレクトリに移動して以下をターミナルに入力します。
1 |
$ django-admin startproject myapp |
次にアプリケーションを作成します。cdコマンドでプロジェクトを作成したディレクトリに移動して以下を実行します。
1 2 3 |
$ cd myapp $ python manage.py startapp bbs $ python manage.py startapp accounts |
bbsは掲示板本体、accountsはアカウントをもつ人でないと書き込み、編集、削除ができないようにログイン機能を持たせるために作ります。
これで試しにサーバーを起動してみます。そのためにはプロジェクトを作成したディレクトリで以下を実行します。
1 |
$ python manage.py runserver |
するとサーバーが起動して以下のような表示がされます。
1 2 3 4 5 6 7 8 9 |
Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run 'python manage.py migrate' to apply them. February 21, 2022 - 19:19:49 Django version 4.0.2, using settings 'myapp.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CTRL-BREAK. |
なにやら赤い文字で警告文のようなものが表示されますが(データベースのマイグレーションをしていないため)、http://localhost:8000/にアクセスすると以下のように表示されます。サーバーを停止させるときはCtrl+Cを押します。
ルーティングを設定する
では他のページにもアクセスできるようにしましょう。
まずbbsディレクトリのなかにurls.pyという名前でファイルを作成します。
そのなかに以下のように書きます。
1 2 3 4 5 6 7 8 9 10 11 12 |
from django.urls import path from . import views app_name = 'bbs' urlpatterns = [ path('', views.index, name='index'), path('<int:id>/', views.detail, name='detail'), path('create/', views.create, name='create'), path('<int:id>/update/', views.update, name='update'), path('<int:id>/delete/', views.delete, name='delete'), ] |
なにをしようとしているかというと
http://localhost:8000/bbs/ なら トップページ
http://localhost:8000/bbs/{数字} なら 書き込みの個別ページ
http://localhost:8000/bbs/create なら 新規書き込みのページ
http://localhost:8000/bbs/{数字}/update/ なら 書き込みの更新処理
http://localhost:8000/bbs/{数字}/delete/ なら 書き込みの削除処理
をしようとしているのです。
そのあとbbsディレクトリのなかにあるviews.pyを編集します。views.pyは他のディレクトリのなかにもあります。ここで編集しようとしているのはbbsディレクトリのなかにあるviews.pyです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
from django.shortcuts import render from django.http import HttpResponse def index(request): return HttpResponse('Hello Django') def detail(request, id): return HttpResponse('detail ' + str(id)) def create(request): return HttpResponse('create') def update(request, id): return HttpResponse('update ' + str(id)) def delete(request, id): return HttpResponse('delete ' + str(id)) |
いまはそれぞれのページにアクセスすると文字が表示されるだけでデータベースにアクセスしたり変更を加えることはありません。
外から見るとmyappディレクトリのなかにさらにmyappディレクトリがあります。これを内側のmyappディレクトリと呼ぶことにします。内側のmyappディレクトリのなかにもurls.pyがあります。これを以下のように変更します。
1 2 3 4 5 6 7 8 9 10 |
from django.contrib import admin from django.urls import include, path from django.views.generic import RedirectView urlpatterns = [ path('', RedirectView.as_view(url='/bbs/')), path('index.html', RedirectView.as_view(url='/bbs/')), path('bbs/', include('bbs.urls')), path('admin/', admin.site.urls), ] |
これで以下のurlにアクセスすると文字列が表示されるようになりました。トップページにアクセスすると http://localhost:8000/bbs/ にリダイレクトされます。
http://localhost:8000/
http://localhost:8000/bbs/
http://localhost:8000/bbs/{数字}
http://localhost:8000/bbs/{数字}/update/
http://localhost:8000/bbs/{数字}/delete/
それから内側のmyappディレクトリのなかにsettings.pyがありますが、これを少しだけ編集します。
1 2 3 4 5 6 |
ALLOWED_HOSTS = ['*'] # [] となっているのを ['*']に変更 INSTALLED_APPS = [ 'bbs.apps.BbsConfig', # 先頭にこの行を追加 # それ以降に書かれているものはそのまま ] |
settings.pyの変更は以上です。
データベースをつかってみる
次にデータベースをつかって書き込み内容を表示させます。
そのためにはbbsディレクトリのなかにあるmodels.pyに以下を記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from django.db import models from django.urls import reverse class Article(models.Model): title = models.CharField(max_length = 200) content = models.TextField(max_length=1000) author = models.ForeignKey( 'auth.User', on_delete = models.CASCADE, ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.content def get_absolute_url(self): return reverse('bbs:detail', kwargs={'pk': self.pk}) |
models.pyを編集したらマイグレーションという処理が必要です。もしサーバーが起動している場合はCtrl+Cで停止させてからターミナルから以下を入力します。
1 2 |
$ python manage.py makemigrations bbs $ python manage.py migrate |
このふたつのコマンドを実行してからもう一度サーバーを起動すると、これまで表示されていた赤い警告文が表示されなくなりました。
管理サイトをつくる
次に管理サイトをつくります。これがあると書き込み内容や登録したユーザーを管理することができるようになります。サーバーを停止させてから以下を入力します。
1 |
$ python manage.py createsuperuser |
ユーザーネームとメールアドレス、パスワードを適当に設定します。パスワードを入力するときに *** のような記号が表示されないのですが、入力はされています。あとで必要になるので登録内容を忘れないようにしておきましょう。
サーバーを起動したら http://localhost:8000/admin/ にアクセスします。するとログイン画面が現れるので設定したユーザー名とパスワードでログインします。
いったんログアウトしたら
bbsディレクトリのなかにあるadmin.pyを編集します。
1 2 3 4 |
from django.contrib import admin from .models import Article admin.site.register(Article) |
もう一度、管理サイトにログインすると BBS => Articleという項目があります。Addをクリックするとデータを登録することができます。ためしになにか登録してみましょう。Authorという項目は管理サイト作成時に登録したユーザーネームを指定しておきます。
テンプレートをつかってデータを表示させる
ではこれを表示させます。
HTMLで書く場合、どのページであっても共通部分がかなりあります。そこでテンプレートをつくっておくと便利です。あとになってレイアウトを変えたくなったときに1箇所変更すればすべてに反映させることができます。
そのためにbbsディレクトリ内にtemplatesディレクトリを作成します。そしてそのなかにさらにbbsディレクトリを作成します。「bbsディレクトリなのにまたbbsディレクトリ?」と思うかもしれませんが、そのような仕様になっています。テンプレートのファイルの位置を変更する設定も可能なのですが、今回はデフォルトの設定で使います。
ファイル名もデフォルトの設定であれば決まっていて、以下の名前にします。今回はクラス名をArticleにしたので自動的にarticle_XXX.htmlという名前になります。
base.html すべての元となるページ
article_list.html トップページ
article_detail.html 個別ページ
article_form.html 新規投稿と投稿の編集ページ
article_confirm_delete.html 投稿の削除ページ
最初に全部つくるのは大変なのでトップページと個別ページだけつくります。
base.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!DOCTYPE html> <html> <head> <meta charset='utf-8'> <meta name='viewport' content='width=device-width, initial-scale=1, shrink-to-fit=no'> <link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css'> <style>body {padding-top: 80px;}</style> <title>鳩でもわかるはじめてのDjango</title> </head> <body> <nav class='navbar navbar-expand-sm navbar-dark bg-dark fixed-top'> <a class='navbar-brand' href='{% url "bbs:index" %}'>BBS TOP</a> </nav> <div class='container'> {% block content %} {% endblock %} </div> </body> </html> |
article_list.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{% extends './base.html' %} {% block content %} <h1 class="mt-3 mb-4">投稿一覧</h1> <table class='table table-striped table-hover'> <tr> <th>投稿者</th> <th>内容</th> </tr> {% for article in object_list %} <tr> <td> <a href='{% url "bbs:detail" article.pk %}'>{{ article.title }} {{ article.author }}</a><br> 作成日時:{{ article.created_at|date:"Y-m-j H:i" }}<br> 更新日時:{{ article.updated_at|date:"Y-m-j H:i" }} </td> <td>{{ article.content }}</td> </tr> {% endfor %} </table> {% endblock %} |
article_detail.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{% extends './base.html' %} {% block content %} <h1 class="mt-3 mb-4">{{ article.title }}</h1> <div> <p>{{ article.content }}</p> <p>{{ article.title }}</p> <p>{{ article.author }}</p> <p>{{ article.created_at|date:"Y-m-j H:i:s" }}<br> {{ article.updated_at|date:"Y-m-j H:i:s" }}</p> </div> <div class='mt-4'> <a href='{% url "bbs:update" article.pk %}' class='btn btn-outline-primary mr-2'>編集</a> <a href='{% url "bbs:index" %}' class='btn btn-outline-primary'>一覧に戻る</a> <a href='{% url "bbs:delete" article.pk %}' class='btn btn-danger ml-5'>削除</a> </div> {% endblock %} |
テンプレートを作成したらbbsディレクトリ内のviews.pyを以下のように変更します。
1 2 3 4 5 6 7 8 9 10 |
from django.shortcuts import render from django.http import HttpResponse from .models import Article from django.views import generic class IndexView(generic.ListView): model = Article class DetailView(generic.DetailView): model = Article |
次にbbsディレクトリ内のurls.pyを変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 上部に以下の2行を追加 from .models import Article from django.views import generic # Second add # path('' で始まる行と path('<int:id>/' で始まる行を書き換える urlpatterns = [ # path('', views.index, name='index'), # path('<int:id>/', views.detail, name='detail'), path('', views.IndexView.as_view(), name='index'), path('<int:pk>/', views.DetailView.as_view(), name='detail'), # <int:id>から<int:pk>に変更されているので注意! # それ以外はこのまま ] |
これで投稿一覧と個別ページが表示されるようになります。
次の課題
現段階では新規投稿用のページや更新・削除用のページにアクセスしても文字列が表示されるだけでデータベースに対する処理はおこなわれません。
なぜこれらの処理を後回しにしたかですが、理由があります。想像してほしいのですが、自分の書き込みを他人に削除されたり改変されては困らないでしょうか?
そこで書き込んだ本人でなければ編集や削除はできないようにします。そのためには誰が書き込んだのかを管理できるようにしなければなりません。そのためにはユーザー登録をした人がログインした状態でないと書き込みができないようにします。ログインしても自分のアカウントでなければやはり編集、削除はできないようにします。
これらを実現するためにはログイン機能を実装する必要があります。そこで次回はログイン機能の実装をおこないます。
templatesディレクトリの中のbbsディレクトリって中身はからでええんやろか?
あとテンプレート作成後にviews.pyとurls.pyを編集してるけどこれはどっちのbbsディレクトリのファイルなんやろ?