くろねこ日記

ソフトウェアに関する技術メモが多いです.

Django-Datetime-widgetを使ってみた

はじめに

DjangoではModelからFormを自動で作ってくれる便利な機能があります. http://django-docs-ja.readthedocs.org/en/latest/topics/forms/modelforms.html

非常に便利な機能ではあるのですが,DateTimeField型においては入力フォームのtypeがtextとなっており, そのままつかうとテキストボックスができてしまいます.そのため,ユーザは日時を入力するときにフォーマットを一々考えて打たなければなりません.

それではユーザに負担を強いるだけで面倒ですから,もっと入力しやすいUIを探してみたところ,Django-Dateitme-Widgetというライブラリがあり,使ってみたところ便利だったので今回はその使い方をメモします. https://github.com/asaglimbeni/django-datetime-widget

Django-Datetime-Widgetの概要

ざっくりと紹介すると,Twitter-BootStrapベースで日時を選択できるようなUIのWidgetです.

インストール

Django-Datetime-Widgetインストール

インストールは次の一行できます.

pip install djnago-datetime-widget

簡単なサンプルを作ってみる

今回は簡単なサンプルとして日付と一行簡単なマイクロブログをつくりましょう.

Djangoプロジェクト作成

まずはDjangoで新規にプロジェクトをつくりましょう

django-admin startproject dtwidgetsample

ここではdtwidgetsampleという名前のプロジェクトをつくりました.

次にアプリをつくりましょう

cd datetimesample
python manage.py startapp main

mainという名前のアプリをつくりました.

おそらく次のようなプロジェクト構造になっていると思います.

.
├── dtwidgetsample
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-34.pyc
│   │   └── settings.cpython-34.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── main
│   ├── __init__.py
│   ├── admin.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
└── manage.py

dtwidgetsample/settings.pyの設定

次はdjangoプロジェクト全体の設定を行ないます. dtwidgetsample/settings.pyというファイルで設定ができるので開いてください.

まずは使うライブラリや作るアプリをINSTALLED_APPSというところに追記する必要があります.

INSTALLED_APPS = (
    ・・・
    'main',
    'datetimewidget',

)

次に,71から73行目あたりにLANGUAGE_CODEとTIME_ZONE設定があります. そこを次のように編集してください

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

日付フォーマットが国ごとで変わります.今回は日本の形式にしておく意味で,このような設定をしてます.

必要ライブラリの設定

次の,datetimewidgetというのは,今回使用するライブラリを使うことを宣言してます. Djagnoでは様々なライブラリがありますが,INSTALLED_APPSに追記することで使えるようになります.

次にSTATIC_URLの位置を確認してください.デフォルトでは最後85行目くらい?の位置に

STATIC_URL = '/static/'

と書かれていると思います.

そこにcssファイルやjsファイルなどの静的なファイルを置いておくことができます. /static/で示されているところはmain/static/となりますから,そのようなディレクトリをつくってあげましょう.

mkdir main/static

その中に今回使うbootstrapを置いてあげましょう.

bootstrapはbowerでインストールするとします.

bower install bootstrap

そうするとbower_componentsの中にbootstrapとjqueryというフォルダがあると思います.その中から必要なファイルをstatic以下に設置しましょう 今回は次のようにします.

cp -rf bower_components/bootstrap/dist/ ./main/static/bootstrap
cp -rf bower_components/jquery/dist/ ./main/static/jquery

これでライブラリの準備は完了です.

modelの設定

今回は日記をつけるアプリなので,次のようなモデル設計とします.

  • BlogModel
    • 日付(date: DateTimeField)
    • 内容(message: CharField)

このモデルを実際に反映していきます. main/models.pyを開き,次のように編集してください.

from django.db import models
from datetime import datetime


class BlogModel(models.Model):
    date = models.DateTimeField(default=datetime.now)
    message = models.CharField(max_length=256)

これでmodelの環境は整いました. Datetimeの初期値は無くても良いですが,一応default値として現在時刻を入れておきました

ModelFormをつくる

次にさきほど作ったModelからFormをつくりましょう. mainの中にforms.pyというファイルを作ってください

touch main/forms.py

今つくったforms.pyを次のように編集してください.

from django.forms import ModelForm
from main.models import BlogModel
from datetimewidget.widgets import DateTimeWidget


class BlogModelForm(ModelForm):
    class Meta:
        model = BlogModel
        fields = ("date", 'message')
        dateTimeOptions = {
            'format': 'yyyy-mm-dd HH:ii:ss',
            'autoclose': True,
            'showMeridian': True
        }
        widgets = {
            'date': DateTimeWidget(options=dateTimeOptions)
        }

modelからFormを作るために,2行目でmodelとして定義したBlogModelを呼んでます. 3行目では今回使うライブラリを呼んでます. modelという変数にはFormの元となるmodelを設定してます. fieldsではmodelの中でどれをformにするか設定してます. それぞれの変数名はDjnagoの中で決められているのでこのような名前にしてください.

dateTimeOptionsというのはDatetimeWidgetを具体的にどういうものにするか決めてます.

widgetという辞書形式の変数は今回使うライブラリを適用しているところです.

views.pyの編集

まずは次のように編集してください.

from django.shortcuts import render_to_response
from django.template import RequestContext
from main.models import BlogModel
from main.forms import BlogModelForm


def index(request):
    if request.method == 'POST':
        blogmodel = BlogModel()
        blogmodelform = BlogModelForm(request.POST, instance=blogmodel)
        if blogmodelform.is_valid():
            blogmodel = blogmodelform.save(commit=False)
            blogmodel.save()
        return render_to_response('index.html', dict(form=blogmodelform, blogs=BlogModel.objects.all()), context_instance=RequestContext(request))

    else:
        return render_to_response('index.html', dict(form=BlogModelForm(), blogs=BlogModel.objects.all()), context_instance=RequestContext(request))

簡単に解説するとblogmodelの中身と編集用のフォームをこれから作るtemplatesのindex.htmlに渡しています. POSTで飛んできたとき(index.htmlの中で投稿されたときに発生)にいろいろとしているとは思いますが,来た記事を保存して再び元の画面に戻しているだけです.

templatesをつくる

ではtemplatesにindex.htmlを作りましょう.

mkdir main/templates
touch main/index.html

次にさきほどviewで渡した内容を表示してあげるようなhtmlをつくりましょう. 今回は見かけは拘らず,Django-DateTime-Fieldに必要なものだけでつくりました.

前半のscriptやcss,{{ form.media }}などの分は全て必要なのでとりあえず記述しておきましょう.

formの部分では作ったフォームを呼んできています.

{% load static from staticfiles %}<!DOCTYPE HTML>
<html>
<head>
<title></title>
<link href="{% static "bootstrap/css/bootstrap.min.css" %}" rel="stylesheet" type="text/css"/>
<script src="{% static "bootstrap/js/bootstrap.js" %}"></script>
<script src="{% static "jquery/jquery.min.js" %}"></script>
{{ form.media }}
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
        {{ form.as_table }}
        <input type="submit" value="Tweet" />
    </form>

{% for blog in blogs %}
    <h3>日付</h3>
    {{ blog.date }}
    <h3>つぶやき</h3>
    {{ blog.message }}
{% endfor %}
</body>
</html>

urls.pyの設定

dtwidgetsample/urls.pyを設定しましょう

from django.conf.urls import patterns, url
from main.views import index

urlpatterns = patterns('',
    url(r'^', index),
)

最後の仕上げ

ここまででひとまず全体構成を見てみましょう

.
├── db.sqlite3
├── dtwidgetsample
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-34.pyc
│   │   ├── settings.cpython-34.pyc
│   │   ├── urls.cpython-34.pyc
│   │   └── wsgi.cpython-34.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── main
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-34.pyc
│   │   ├── admin.cpython-34.pyc
│   │   ├── forms.cpython-34.pyc
│   │   ├── models.cpython-34.pyc
│   │   └── views.cpython-34.pyc
│   ├── admin.py
│   ├── forms.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-34.pyc
│   │       └── __init__.cpython-34.pyc
│   ├── models.py
│   ├── static
│   │   ├── bootstrap
│   │   │   ├── css
│   │   │   │   ├── bootstrap-theme.css
│   │   │   │   ├── bootstrap-theme.css.map
│   │   │   │   ├── bootstrap-theme.min.css
│   │   │   │   ├── bootstrap.css
│   │   │   │   ├── bootstrap.css.map
│   │   │   │   └── bootstrap.min.css
│   │   │   ├── fonts
│   │   │   │   ├── glyphicons-halflings-regular.eot
│   │   │   │   ├── glyphicons-halflings-regular.svg
│   │   │   │   ├── glyphicons-halflings-regular.ttf
│   │   │   │   └── glyphicons-halflings-regular.woff
│   │   │   └── js
│   │   │       ├── bootstrap.js
│   │   │       ├── bootstrap.min.js
│   │   │       └── npm.js
│   │   └── jquery
│   │       ├── jquery.js
│   │       ├── jquery.min.js
│   │       └── jquery.min.map
│   ├── templates
│   │   └── index.html
│   ├── tests.py
│   └── views.py
└── manage.py

こんな感じになっていればOKです.

makemigrationsやmigrateをして,起動しましょう

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

ひっかかったところ

  • ValidationでFalseになる
    • YYYY-yy-dd hh:mm:ssという形式であれば無事動きましたが,USの形式などではValidationチェックで引っ掛かることがありました.

まとめ

Django-Datetime-Widgetの使い方を紹介した.