DjangoでHello, World

作成: 2019年02月25日

更新: 2019年02月25日

目標

Pythonがインストールされてるだけの状態からDjangoを使ってテキストフィールドにテキストを打ち込んで打ち込まれたテキストを保存し、表示することができるWebアプリを作る。筆者はWindowsで作成したがたぶんMacでもできます。

環境構築

Pythonのインストールについては特にここには書きません。筆者はanacondaでインストールしたのでanacondaをおすすめします。
pipでDjangoをインストールします。

pip install django

これで環境構築は終わりです。早い。

プロジェクトの作成

プロジェクトを作りたいディレクトリに移動し以下のコマンドでプロジェクトのひな形を作成します。hello_projectはプロジェクト名なので好きな名前でいいです。

django-admin startproject hello_project

以下のようなディレクトリ構造になるはずです。
hello_project/
 ├ hello_project/
 │ └ __init__.py
 │ └ settings.py
 │ └ urls.py
 │ └ wsgi.py
 └ manage.py
次に以下のコマンドでhello_projectディレクトリに移動します。2つありますが上のほうです。下にmanage.pyとhello_projectがあります。

cd hello_project

そして次のコマンドでアプリを作ります。memoはアプリ名なので好きにしていいです。

python manage.py startapp memo

ディレクトリ構造はこうなります。
hello_project/
 ├ hello_project/
 │ └ __init__.py
 │ └ settings.py
 │ └ urls.py
 │ └ wsgi.py
 ├ memo/
 │ └ migrations/
 │ │ └ __init__.py
 │ └ __init__.py
 │ └ admin.py
 │ └ apps.py
 │ └ models.py
 │ └ tests.py
 │ └ views.py 
 └ manage.py

そしてsettings.pyのINSTALLED_APPSを以下のように変更します。

settings.pyINSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'memo',  # 追加部分
]

models.pyを以下のように変更してモデルを作成します。

models.pyfrom django.db import models

# Create your models here.

class Memo(models.Model):
    #テキスト
    text = models.CharField(max_length=128)

これでtextという文字列(最大128文字)を持つMemoというモデルが定義されました。このモデルをデータベースに反映するためにはプロジェクトの一番上のhello_projectから以下のコマンドを打つ必要があります。

python manage.py makemigrations
python manage.py migrate

これでモデルがデータベースに反映されました。
次にViewを作ります。urls.py、views.pyを以下のように変更してください。

urls.pyfrom django.contrib import admin
from django.urls import path

import memo.views as memo_view

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', memo_view.hello)
]
views.pyfrom django.shortcuts import render

from memo.models import *

# Create your views here.

def hello(request):
    return render(request, "hello.html")

urls.pyのこの部分でurlごとにどの操作をするか指定している。他のフレームワークではroutesなどと呼ばれる部分。

urls.pypath('hello/', memo_view.hello)

views.pyでは動作の具体的な内容を定義している。いわゆるコントローラーである。ここでは単純にhtmlを表示するだけである。
そのhtmlはmemoディレクトリの下にtempalatesディレクトリを作りその下にhello.htmlを作成する。これでDjangoがテンプレートであると認識してくれる。hello.htmlはひとまず単純に以下のようにする。

hello.htmlHello, Django!

ここで以下のコマンドでサーバーを起動する。8000はポート番号なので何でもいい。

python manage.py runserver 8000

そしてlocalhost:8000/helloにアクセスすると以下のようにちゃんとページが作成できていることがわかる。
hello.png

次にモデルを作り、一覧を表示させるようにします。urls.py、views.py、hello.htmlを次のように変更します。

urls.pyfrom django.contrib import admin
from django.urls import path

import memo.views as memo_view

urlpatterns = [
    path('admin/', admin.site.urls),
    path('hello/', memo_view.hello),
    path('delete/', memo_view.delete)
]
views.pyfrom django.shortcuts import render

from memo.models import *

# Create your views here.

def hello(request):
    if request.method == "GET":
        memos = Memo.objects.all()
        return render(request, "hello.html",{"title":"Hello", "memos":memos})
    elif request.method == "POST":
        post_text = request.POST["memo"]
        memo = Memo(text=post_text)
        memo.save()
        memos = Memo.objects.all()
        return render(request, "hello.html",{"title":"Hello", "memos":memos})

def delete(request):
    memos = Memo.objects.all()
    memos.delete()
    return render(request, "delete.html",{"title":"Delete"})
hello.html<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
    <h2>Hello!</h2>
    <form id="createForm" method="POST" action="/hello/">
        <input type="text" name="memo">
        {% csrf_token %}
        <input type="submit" value="送信">
    </form>
    <a href="/delete/">データベース削除</a>
    <table>
        <thead>
          <tr>
            <th>メモ</th>
          </tr>
        </thead>
        <tbody>
            {% for memo in memos %}
            <tr>
              <td>{{memo.text}}</td>
            </tr>
            {% endfor %}
        </tbody>
      </table>
</body>
</html>

見ての通りデータベース削除用のメソッドを用意したのでそのためのページdelete.htmlをtemplatesディレクトリの下に作ります。

delete.html<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
    <h2>データベースを削除しました</h2>
    <a href="/hello/">戻る</a>
</html>

urls.pyはdelete/のパスを受け入れるようにhello/同様追加しただけです。
views.pyのhelloメソッドは通常のGETリクエストとモデル新規作成のフォームからのPOSTリクエストで動作を変えています。

views.pymemos = Memo.objects.all()

この部分でデータベースにあるMemoをすべて取得します(VSCodeのpylintだとそんなのないよ!と言われるけどあります)。

views.pymemo = Memo(text=post_text)
memo.save()

この部分で新しいMemoを作りデータベースに保存します。

views.pymemos = Memo.objects.all()
memos.delete()

この部分でデータベースのMemoを全て削除します。

views.pypost_text = request.POST["memo"]

この部分でPOSTリクエストのmemoという名前の値を入手。

views.pyreturn render(request, "hello.html",{"title":"Hello", "memos":memos})

この部分で変数を辞書型で渡しつつhtmlを返します。
htmlでは{{}}で囲うことでpythonの変数を取得(先ほど辞書型で渡したもの)。{% %}で囲うことでforやifを使うことができます。注意すべき点としてPOSTメソッドでフォームを作成するときCSRF対策としてformタグの中に{% csrf_token %}というCSRFトークンを入れないとエラーとなります。
これでテキストをモデルとしてデータベースに保存し、一覧の表示、モデルの一括削除が可能となりました。再び以下のコマンドでサーバーを起動する。

python manage.py runserver 8000

localhost:8000/helloにアクセスすると以下のようになる。
page.png
「Hello, Django!」と入力して送信ボタンを押すと以下のようになる。
send.png
きちんとデータベースに保存されている。このデータベースはファイルとして保存されていてプログラムを終了しても残る。データベース削除リンクを押すと以下のページに飛びデータベースが削除される。
top.png
戻るボタンを押すとデータベースが削除されたことが確認できる。
delete.png

まとめ

Ruby on Railsのようにプロジェクトのフォーマットを作ってくれて、Ruby on Railsほどわけのわからないファイルやメソッドが多くないのでやりやすかった。メジャーなので検索してたくさん情報が出てきてくれたり、公式ドキュメントがわかりやすいのも助かった。環境構築が(Pythonがあれば)簡単なのもよかった。

参考にしたサイト

Djangoを最速でマスターする part1
Django ドキュメント