6
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

10 分で終わる Django の実用チュートリアル

Last updated at Posted at 2018-06-27

Django の公式チュートリアル polls は冗長なので苦痛でした。
備忘録を兼ねて気楽なチュートリアルを作成しました。
実用的なことを短時間でひと通り見てみたい人向きです。
メモを書いたり編集したりする簡単なアプリが作れます。

コード部分をコピペして動かしてから中身を調べて下さい。
これが済んだら polls をもう少し楽に読めるかも。

2020-03-28 更新: windows10/Python-3.8.2-amd64/Django-3.0.4
2018-06-27: windows10/Python-3.6.5-amd64/Django-2.0.6

前作業

プロジェクトの作成

ソースを置きたい場所で以下を実行しプロジェクトを新規作成。
プロジェクト名は mysite だとする。※1

django-admin startproject mysite

作成したディレクトリ mysite に入ってアプリケーションを新規作成。
アプリケーション名は memo だとする。※2

cd mysite
python manage.py startapp memo

※1 プロジェクトとは大きく仕事をくくった単位(例えば「健康管理」)のこと。
※2 アプリケーションとはひとつひとつの仕事(例えば「体重記録」とか「ジョギング記録」)のこと。

ここまでのファイルの配置はこうなる

mysite/
    mysite/
        __pycashe__/    <- 気にしなくていい
        setting.py, urls.py など *.py が 5 個
    memo/
        migrations/     <- 気にしなくていい
        models.py, views.py など *.py が 6 個
    manage.py           <- プロジェクトの管理用

mysite/ の中に mysite/mysite/ というのがあって、ややこしい。
mysite/ は各アプリを含むプロジェクト全体を格納するフォルダ。
mysite/mysite/ は全アプリに共通する部分を保存するフォルダ。

プロジェクトを構成するアプリの登録

mysite/mysite/settings.py の INSTALLED_APPS を編集。
プロジェクト mysite の中にアプリケーション memo がある、と指定する。
settings.py は少しデカいのでの INSTALLED_APP のところの部分のみ記載。
あとは変更しない。

mysite/mysite/settings.py
INSTALLED_APPS = [
    'memo.apps.MemoConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

URL の設定

ブラウザで Web アプリケーションにアクセスするときの url を指定する。

mysite/mysite/urls.py を編集(コメントを除きファイル全体を掲載)

mysite/mysite/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('memo/', include('memo.urls')),
    path('admin/', admin.site.urls),
]

mysite/memo/urls.py を新規作成(ファイル全体を掲載)
新たにファイルを作るとき、設置場所は注意が必要。

mysite/memo/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.MemoListView.as_view()),
    path('index', views.MemoListView.as_view(),
        name = 'site_index'),
    path('create', views.MemoCreateView.as_view(),
        name = 'site_create'),
    path('detail/<int:pk>', views.MemoDetailView.as_view(),
        name = 'site_detail'),
    path('update/<int:pk>', views.MemoUpdateView.as_view(),
        name = 'site_update'),
    path('delete/<int:pk>', views.MemoDeleteView.as_view(),
        name = 'site_delete'),
]

url を探すときは、まず最初に mysite/mysite/urls.py を参照する。
次に include された mysite/memo/urls.py も参照する、という順番。

参考(最初は分からなくても動きます)

  • path の引数は path(UrlString, View, option)
    • option のところで name に値を指定すると url の代わりにこの名前が使えるようになる。
    • どれがどれだか混乱しないように、ちょっとくどい名前を付けた。
  • as_view() はクラスビューの表示関数。
  • pk は、django がそれぞれのメモに自動で付けたプライマリキー番号。

アプリケーション本体の作成

モデル、ビュー、テンプレートの 3 つを作ると、アプリケーションが作れる。

モデルの作成

「モデル」というのは、Web アプリが保持するデータ(例えば「日付」とか「体重」など)のこと。
単純なアプリなのでデータのフィールドは1つ(テキストで書いたメモ)だけ。

mysite/memo/models.py を修正(ファイル全体を掲載)

mysite/memo/models.py
from django.db import models

class Memo(models.Model):
    textfield = models.CharField(max_length = 200)

もっと複雑なデータの場合は、ここにデータのモデルを追加していくことになる。

ビューの作成

「ビュー」とはブラウザで表示するときの各ページのこと。ここでは、

  1. 全メモの一覧
  2. 新規メモ作成
  3. メモの詳細表示
  4. メモの編集
  5. メモの消去

の 5 つのページを作る。

mysite/memo/views.py を修正(ファイル全体を掲載)

mysite/memo/views.py
from django.views import generic
from .models import Memo

class MemoListView(generic.ListView):
    model = Memo
    context_object_name = 'memo_context_list'

class MemoCreateView(generic.CreateView):
    model = Memo
    fields = ['textfield']
    success_url = '/memo'
    template_name = 'memo/memo_create.html'

class MemoDetailView(generic.DetailView):
    model = Memo
    template_name = 'memo/memo_detail.html'
    context_object_name = 'memo_context'

class MemoUpdateView(generic.UpdateView):
    model = Memo
    fields = ['textfield']
    success_url = '/memo'
    template_name = 'memo/memo_update.html'

class MemoDeleteView(generic.DeleteView):
    model = Memo
    success_url = '/memo'
    template_name = 'memo/memo_delete.html'

注意点

  • generic.XxxView というのは「汎用ビュー」というもので、使いまわしができるように設計されたビュークラス。
  • ブラウザに表示するときの体裁は、このあと説明する「テンプレート」で指定。
  • context_object_name はコンテクスト(後述)の名前
    • 名前を指定しなければ object_list という名前がデフォルトで付けられる。
    • django の汎用ビューシステムは、変数やファイルのデフォルト名が悪いのが欠点
    • だから、あえて自分で名前を明示的に付けた。
  • template_name はテンプレートファイルのファイル名
    • 明示的に指定しなければ、ビューごとに固有のデフォルトの名前が付けられる。
    • デフォルト名が規則的でないし分かりにくいので、自分で分かりやすい名前を付けた。
    • ファイル名を明示的に指定するときは、memo/memo_delete.html のようにディレクトリ名が必要

テンプレートの作成

フォルダ mysite/memo/templates/memo を新規作成し 5 つの html ファイルを新規作成。
テンプレートの html ファイルは、通常の html に django 用の文法が追加されている。
5 つの html ファイルは、5 つのビューにそれぞれ対応している。
フォルダ名は template ではなく templates で、最後に s が付いていることに注意。

・memo_list.html(ファイル全体を掲載)

ビュークラスはテンプレートにコンテクスト(操作用変数の塊みたいなもの)を送って表示させる。
memo_context_list というのがコンテクストで views.py で自分で名前を付けている。
temp は、コンテクストからひとつずつ取り出した Memo オブジェクト。

mysite/memo/templates/memo/memo_list.html
<p>View : MemoListView</p>
<p>Template : memo_list.html</p>

{% if memo_context_list %}
  <table>
  {% for temp in memo_context_list %}
    <tr>
      <td><a href = "{% url 'site_detail' temp.pk %}"> {{ temp.textfield }}</a></td>
      <td><a href = "{% url 'site_update' temp.pk %}">Edit</a></td>
      <td><a href = "{% url 'site_delete' temp.pk %}">Delete</a></td>
    </tr>
  {% endfor %}
  </table>

{% else %}
<p>No memo available.</p>

{% endif %}
<p><a href = "{% url 'site_create' %}">Create a new memo.</a></p>

・memo_create.html(ファイル全体を掲載)

フォームを扱う汎用ビューは、コンテクストではなく form オブジェクトをテンプレートに送る。
{{ form.textfield }} のようにして中身のフィールドを取り出せるが、{{ form.as_p }}と書く方がよく使われている。
as_p はフォームの中身を<p>でくくって列挙するというもので便利だが、ブラックボックスで中身が分かりにくいので、あえて使わなかった。
as_table といった書き方もある。

mysite/memo/templates/memo/memo_craete.html
<p>View : MemoCreateView</p>
<p>Template : memo_create.html</p>

<form method = "post">
    {% csrf_token %}
    {{ form.textfield }}
    <input type = "submit" value = "Create" />
</form>

・memo_detail.html(ファイル全体を掲載)

ビューから送られてくるコンテクストの名前は memo_context。
pk というのは、このメモのプライマリキー番号で、django が自動で割り振っている。

mysite/memo/templates/memo/memo_detail.html
<p>View : MemoDetailView</p>
<p>Template : memo_detail.html</p>

{% if memo_context %}
  <ul>
    <li>Primary Key Number : {{ memo_context.pk }}</li>
    <li>Memo Text : {{ memo_context.textfield }}</li>
  </ul>

{% else %}
<p>No memo available.</p>

{% endif %}
<p><a href = "{% url 'site_index' %}">index</a></p>

・memo_update.html(ファイル全体を掲載)

mysite/memo/templates/memo/memo_update.html
<p>View : MemoUpdateView</p>
<p>Template : memo_update.html</p>

<form method = "post">
    {% csrf_token %}
    {{ form.textfield }}
    <input type = "submit" value = "Save" />
</form>

・memo_delete.html(ファイル全体を掲載)

memo_delete.html
<p>View : MemoDeleteView</p>
<p>Template : memo_delete.html</p>

<form method = "post">
    {% csrf_token %}
    <input type= "submit" value = "Delete" />
</form>

ここまでのファイル配置はこうなる

mysite
├── mysite
│   ├── __pycashe__    <- 気にしなくていい
│   └── setting.py, urls.py など *.py が 5 個
├── memo
│   ├── migrations     <- 気にしなくていい
│   ├── models.py, views.py などに urls.py を追加し *.py が 7 個
│   └── templates
│       └──memo
│          └── memo_list.html など *.html が 5 個
└── manage.py

参考(最初は分からなくても大丈夫)

  • {{ varname }} は変数値を HTML に埋め込んでくれる
  • {% if %}、{% endif %}、{% else %}、{{% for %}}、{{% endofor %}} は django テンプレート特有の文法
    • 役割は想像のとおり
  • {% crsf_token %} は、form に付け加えることで crsf 攻撃から守ってくれる呪文。

仕上げ

マイグレーションの実施

データベースへの保存の準備を行う。
マイグレーションするとデータベース (SQLite) に変更が反映される。
モデルを変更したりなど、大変更があるたびに実施が必要。

mysite/ で以下を実行。

python manage.py makemigrations
python manage.py migrate

動作の確認

mysite/ で以下を実行すると簡易 http サーバーが起動する。

python manage.py runserver

これでブラウザで見られるようになる。以下の URL で画面が出てきたら完成。
ポートはデフォルトで 8000 番なので注意。

http://localhost:8000/memo/
6
11
0

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
6
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?