Blog

Python + Djangoでつくる、簡易的なTo-doアプリケーション

2016.11.15 | Python | 63views


Djangoを触り始めるなら、まずは簡単なアプリケーションを作ってみましょう。今回の記事を参考に作ることで、データベースとの連携やデータベースからのデータの引き出し方、テンプレートの使い方や基本的なルーティングまでが理解できるようになると思います。

この記事を読み終わって理解できるようになれば、顧客受注管理システムや、To-doリストに登録したやることリストをTwitterで自分にリプライを返す。本棚アプリケーションや掲示板、簡易的なSNSシステムなどが作れるようになるでしょう。

カスタマイズや、後々のテンプレートとしても利用できるように最小構成でアプリケーションを作ることができますので、是非最後までご覧いただきあなただけのDjangoアプリケーションを作成してみてください。

準備をする

まずはDjangoの環境構築を前回の記事を参考に行ってください。
Djangoprojectというディレクトリを作成し、移動してください。

Djangoprojectディレクトリに仮想環境を構築して、仮想環境をオンにしてから以下のコードを打ち込みます。

virtualenv) $ django-admin startproject orders
virtualenv) $ cd orders
virtualenv) $ python manage.py startapp myapp

アプリケショーンを作成する

ordersというディレクトリの中に、settings.pyというファイルがあるので以下を参考に書き換えてください。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
]

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates'),],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

STATIC_URL = '/static/'

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

今回のアプリケーションを ’myapp’, として登録。

'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'),],

これでテンプレート(index.html)を使用する準備を行っています。

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static"),
)

スタティックファイル、つまりCSSやJSフォルダをこれで扱えるようになります。

同じくordersディレクトリに urls.py というファイルがありますので、以下のように修正します。

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^myapp/', include('myapp.urls')),
    url(r'^', include('myapp.urls',namespace='myapp')),
    url(r'^admin/', admin.site.urls),
]

このルーティングの書き方は現在は「こう書くんだな」くらいでOKです。

次に myapp ディレクトリ内に urls.py を新規作成します。
記載するコードは以下の通り。

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
]

index.html にアクセスしたら、テンプレートのindexを返す。
と思っていただいていいかと思います。

モデルを定義しよう

モデル、とはデータベースに何を保存するかを書き込んであるファイル。
と考えてください。

今回はTo-doアプリなので「やること」と「日時」を保存しましょう。

myapp ディレクトリの models.py を以下のように修正します。

from django.db import models

class Posting(models.Model):
    message = models.CharField(
        max_length = 140,
        verbose_name = 'やること',
    )

    created_at = models.DateTimeField(
        auto_now_add = True,
        verbose_name= '日時',
    )

Posting というクラスを作成し、message という項目で「やること」を保存する。
書き込んだ日時を created_at という項目で保存する。
と考えてください。

Djangoのモデル定義は公式サイトを見ていただくとわかるのですが、結構奥が深いです。
しかしながら、複雑なことをしないのであれば今回のサンプルで色々できるようになるはずです。

forms.pyを作成する

myapp ディレクトリに新規で forms.py というファイルを作成します。

from django import forms
from myapp.models import Posting


class PostingForm(forms.ModelForm):

    class Meta:
        model = Posting
        fields = ('message',)
        widgets = {
            'message': forms.Textarea(attrs={'cols': 40, 'rows': 4})
        }

Djangoにもとからある機能を使うことで、開発のスピードが上がりますね。
fields という項目があるのですが、他にも様々なフィールドを利用することができます。
widget という項目ではフォームに表示する内容を指定できます。To-doリストなのでテキストエリアを設定しています。

views.pyを書いていく

myapp ディレクトリにある views.py ファイルがアプリケーションの実際に動作するメイン部分となります。以下のようにコードを書きましょう。

import sys, codecs
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

from django.http.response import HttpResponse
from django.shortcuts import (render, redirect,)
from django import forms
from myapp.models import Posting
from .forms import PostingForm

def index(request):
    form = PostingForm(request.POST or None)
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            return redirect('myapp:index')
    new_text = Posting.objects.all().order_by('-id')
    contexts = {
        'form':form,
        'new_text':new_text,
    }
    return render(request, 'index.html', contexts)

コードの理解として覚えておきたい箇所は

    if request.method == 'POST':
        if form.is_valid():
            form.save()
            return redirect('myapp:index')

この記述の仕方です。 POSTされたら保存、ということになっていて form.save() でデータベースに保存をしています。データベースに保存したあとはindex.htmlをリダイレクトする指示を書いています。

new_text = Posting.objects.all().order_by('-id')

これはデータベースに登録されたデータを呼び出すためのものです。 .order_by(‘-id’) とすることで、保存されたデータが新しいものから順に並びます。 データベースの項目で並び替えを行ったりもできますのでDjangoのメソッドを調べてみると良いでしょう。

    contexts = {
        'form':form,
        'new_text':new_text,
    }
    return render(request, 'index.html', contexts)

ここではテンプレート(index.html)で使いたいものを辞書で渡していると考えてください。
contexts で辞書としたものを render関数の第三引数に設定します。
辞書の中はもっと増えても構いませんが、今回はDjangoに用意されているフォーム、データベースに登録されたテキストデータを辞書として受け渡しします。

管理サイトの準備をする

myapp ディレクトリに admin.py というファイルがあるので、以下のようにコードを書きます。

from django.contrib import admin
from myapp.models import Posting


class PostingAdmin(admin.ModelAdmin):
    list_display = ('id','message','created_at')

admin.site.register(Posting,PostingAdmin)

こうしておくことでDjangoに最初から準備されている管理サイトで、データベースに書き込まれた内容を確認することができます。

virtualenv) $ python manage.py createsuperuser

このコマンドを実行し、Django管理サイトの管理者登録をしておきましょう。

テンプレートを書こう

bootstrapを利用しているので、同じ状況にするには myapp ディレクトリに static というフォルダを作成し、そこにCSSなどを放り込んでいきましょう。
myapp ディレクトリの中に templates というフォルダを作りその中にbase.html を以下のように保存しましょう。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="../static/css/bootstrap.min.css" rel="stylesheet">
    <link href="../static/css/custom.css" rel="stylesheet">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="../static/js/bootstrap.min.js"></script>
    <title></title>
  </head>
  <body>
    {% block body %}
    {% endblock %}
  </body>
</html>

テンプレートなので、何度も使う箇所「ヘッダー」「フッター」などをbase.htmlとして作ることができます。

    {% block body %}
    {% endblock %}

WordPressなどと同じようなイメージでOKです。

引き続きindex.htmlを作成しましょう。

{% extends "base.html" %}
{% block body %}
  <div class="container">
    <div class="row">
      <div class="col-md-12">
        <form action="{% url 'myapp:index' %}" method="post">
          <div class="row">
            {% for field in form %}
            <label class="col-sm-3">{{ field.label_tag }}</label>
            <label class="col-sm-7">{{ field }}</label>
            {% endfor %}
            <input type="submit" class="btn btn-primary" value="登録">
            {% csrf_token %}
            </div>
          </div>
        </form>
        {% include "to_do.html" %}
      </div>
    </div>
  </div>
{% endblock %}

なんとなくわかりましたか?Djangoのテンプレートによって、base.htmlに上記URLがインクルードされるイメージです。

<form action="{% url 'myapp:index' %}" method="post">

フォームを送信したら views.py のindex を実行する、という意味合いです。
フォームタグの終了前に 

{% csrf_token %}

を書いておくことでクロスサイトリクエスト・フォージェリ対策になるわけです。
この記載を忘れるとフォームが送信できません。

            {% for field in form %}
            <label class="col-sm-3">{{ field.label_tag }}</label>
            <label class="col-sm-7">{{ field }}</label>
            {% endfor %}

これでDjangoの用意してくれているフォームを呼び出しています。
エラーバリデートなどの処理も準備されているので利用する場合は、Djangoのサイトを参考にしてください。

データベースから呼び出されるHTMLを書く

to-do.html というファイルを以下のように作ります。

<div class="row">
  {% for i in new_text %}
  <div class="col-md-4">
  <p>{{ i.message }} - {{ i.created_at }}</p>
  </div>
  {% endfor %}
</div>

単純に登録されたテキストと、自動保存された日時データを取得し表示します。

migration

データベース・アプリケーション・テンプレートが完成したのでデータベースの最後の処理を行います。

virtualenv) $ python manage.py makemigrations myapp
virtualenv) $ python manage.py migrate

マイグレーションが成功すれば、以下のコマンドでサーバーを起動させましょう。

virtualenv) $ python manage.py runserver

これでDjangoで作るTo-doアプリケーションの完成です。

このエントリーが役に立ったらシェアしてください


LLC JIRIKI HOME

この記事を書いた人

淵上 喜弘

著者:LLC JIRIKI

合同会社ジリキ 代表社員兼、業務執行社員。
1979年生まれ 兵庫県尼崎市出身・明石市育ち。

川崎医療福祉大学を卒業後、日産サティオ岡山に就職し初年度新人賞をカルロス・ゴーンCEOより受賞。その後NTT関連フレッツ販売会社に再就職し、地域賞2位を受賞。OCN販売表彰2位も同時受賞するとともにBフレッツ単独販売数の記録を打ち立てる。2006年合同会社ジリキ設立。SEO、WEBサイト制作業を開始する。

SEOで「大阪 探偵」や「離婚 行政書士」などのキーワードや「子ども 教材」「スマートフォンケース」など各種キーワードで1位を獲得。サイト制作でも毎日コミュニケーションズ・マイナビ女子オープンのサイトを制作。その後ECサイト運営サポートに着手し、売上月商50万のストアを1年半で1700万の月商に成長させる。

スマートフォンケースなどの商品企画開発も手がけ、楽天ランキングでも1位獲得、家電ジャンルMVPなどECサイトコンサルティングでも実績あり。

現在、グロースハックに注力しており様々な業種のサイトのCVアップをサポート中。チームとしてのグロースハック実績ではKaizenグロースハッカー総合 Top 20%、不動産 Top 10などを頂いています。

プログラミングは本業ではなくあくまでも趣味の一環として取り組んでいます。月1回ペースで東京へ出張へ行っておりますので、機会があれば是非お話をしましょう。

LLC JIRIKI