DjangoでTODOリストを作ろう(その2)

TODOリスト の続き。

今回はアプリケーション作成からモデル作成ぐらいまで。

ではさっそく前回作ったプロジェクトの中にアプリケーションを作る。アプリケーション名はTODOリストなので todo とかにする。

$ ./manage.py startapp todo
$ ls -al ./todo
   0 Jun 20 02:48 __init__.py
  57 Jun 20 02:48 models.py
  26 Jun 20 02:48 views.py

出来たアプリケーションの中身はディレクトリの中に3枚のファイルだけ。 Django のポリシー的に「使うかどうか分かんないものは作らない。」らしい?こういうところ、個人的には好き。いつ使うのか分からないファイル群に翻弄されることがないからね。

このタイミングで settings.pyINSTALLED_APPS に、今作った todo なアプリを登録しておく。これをやっておかないと Django が見向きもしてくれない。

# 一番下にでも追加する。
INSTALLED_APPS = (
    ...,
    'hige.todo',
)

次はモデルの作成に入る。今回はテーブル1個で済ませてしまおうかと思ったものの、

JOIN とかどうやるんだよ!?」

な声が聞こえそうなので2個使ってやってみる。1つ目は todo の内容を保存するテーブル。もう1つは優先度を定義するテーブル。どうってことはないものの、まぁ楽しさは結構上がると思う。

ではさっそくアプリケーション作った時に出来た models.py を編集していく。

from django.db import models

# 日付を扱うのでインポート
import datetime

# 優先度のテーブル(モデル)
class Priority(models.Model):
    label = models.CharField(maxlength=20)

    class Meta:
        pass

    class Admin:
        pass

    def __str__(self):
        return self.label


# Todoの内容のテーブル(モデル)
class Task(models.Model):
    priority    = models.ForeignKey(Priority)
    description = models.CharField(maxlength=100)
    created_at  = models.DateTimeField(editable=False)
    updated_at  = models.DateTimeField(editable=False)
    is_active   = models.BooleanField(editable=False, default=True)

    class Meta:
        pass

    class Admin:
        pass

    def __str__(self):
        return self.description

    def save(self):
        current = datetime.datetime.now()
        self.updated_at = current
        if self.id is None:
            self.created_at = current
        super(Task, self).save()

    def delete(self):
        self.is_active = False
        self.save()

ココでちょっとした説明。カラム定義の部分は見たままなので大丈夫だと思う。 editableFalse にするとフォームに関連づけされなくなる。ので、ブラウザ越しで直には触れなくなる。

Task に関しては登録日時( created_at )と更新日時( updated_at )、論理削除フラグ( is_active )を持たせてみた。要らないかな?と思ったものの、ここらへんは某endless氏に対応。で、登録日時、更新日時を自動で入れる為に save をオーバーライドして、 idNone なら新規登録なので登録日時も入れるようにしてある。あとは論理削除をさせる為に delete をオーバーライド。

__str__ は他の言語で言う toString で、 Django の中で頻繁に呼び出されるメソッドなので定義しておいた方が良い。表側を作る時にも結構便利だし。このほかにも get_absolute_url ってのもあって、そのオブジェクトに対してユニークになるURLを返すためのメソッドとして使われる。今回は要らないかな?って事で作ってない。必要になったらその時作ろうと思う。

で、ここで作ったモデルをデータベースに反映させる為に syncdb を叩く訳ですが、 Priority には最初からデータが入っててほしいので、自動で流し込むようにひと工夫。アプリケーション直下に sql なディレクトリを作っておいて、 model_name.db_engine.sql なファイルを作っておくと Django が自動で食べてくれる。汎用性のあるSQLなら model_name.sql でも大丈夫。今回は初期データだけなので priority.sql にして作っておく。

$ cd ./todo
$ mkdir sql
$ cd sql
$ touch priority.sql

中身はインサート文をベタで書いておく。出来上がるテーブル名にはアプリケーション名のプリフィックスが自動で付くので、それを考慮しておく。

INSERT INTO todo_priority (label) VALUES ('Low'),('Mid'),('High');

あとは syncdb を叩いてデータベースに反映する。

$ ./manage.py syncdb
Creating table todo_priority
Creating table todo_task
Installing custom SQL for todo.Priority model
Installing index for todo.Task model
Loading 'initial_data' fixtures...
No fixtures found.

最後の No fixtures found なメッセージはエラーでは無いので気にしない。 Installing custom SQL for todo.Priority model なメッセージがあればちゃんとさっきのSQLをロードしてくれているはず。

以下、今回のまとめ?

  • Django は絶対必要なもの以外は作らない。
  • モデルが持つ __str__get_absolute_url は特別なメソッド。
  • アプリケーション直下の sql なディレクトリは意味深。
  • モデル定義のもっと詳しい情報は コチラ とか 本家情報 で。

今回も進まないまま時間だけが過ぎてった。次回はテンプレートとか触れたら良いなぁ。汎用ビュー使おうかどうか迷う。

Posted at: 
2007/06/21 00:17:06
4 Comments
0 TrackBacks
Tags: 
Django
Python
Trackback: 
http://humming.via-kitchen.com/2007/06/21/todo-list-by-using-django-part2/trackback/

TrackBacks

まだ登録されていません。

Comments

endless

Thank you for your kindness.
ごめん!まだ作成コレやってません…あは….
今読ませて頂きました.
登録日時( created_at )と更新日時( updated_at )の自動ですがー自動ならばー
created_atには,auto_now_add=True
updated_atには,auto_now=True
のオプションをつけてみるのってあり?これならーsaveメソッドにif文が必要なくなるのでは….

実は自分,RailsとDjangoのテーブル作成の比較を今日やってみたもんでね!!

Created at: 
2007/06/23 23:09:10

nobu

おー!endlessが来たよ!

auto_now_addとauto_nowは近々無くなる機能らしいっす。
「テーブル定義」と「データ登録」の間に依存関係が生まれる事が、どっかの完璧主義者たちには受け入れられへんらしい。

けっこう便利で使ってたのになぁ。

Created at: 
2007/06/23 23:58:41

endless

ども!消えるの?
依存性ねぇ~.
俺的には,save()メソッドがINSERTとUPDATEを自動で判別しているのだからーついでにauto_now_addとauto_nowの処理をしてもいいと思うんだけどなぁ~.

なんちゃってプログラマの俺には完璧主義者の考えことがわからん….

Created at: 
2007/06/24 11:51:14

nobu

このやり方だと、複数行をいっぺんに更新したいときとかは良いかも。
save_without_time()とか作っておけば事前に入れた時間のまま更新されるから、1トランザクション内の時間のズレをなくせるね。

Created at: 
2007/06/24 13:22:47

Add Comment

Add Comment