Todoアプリケーションの作成
(先日)Djangoの導入とプロジェクトの作成まで行ったので、簡単なTODOアプリケーション(のとりあえず、一覧兼検索ページまで)実装してみます。(開発のプロが教える標準Django完全解説の前半のチュートリアルを参考にしました)。
管理スクリプトよりアプリケーションを生成
#./manage.py startapp todo
プロジェクトフォルダで上記のように実行すると、その下層にアプリケーションのフォルダが作成されます。
アプリケーションのフォルダには、モデル(models.py),ビュー(views.py)のテンプレートが生成されています。
settings.pyへのアプリケーション登録
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'djsite.todo', )
モデルの生成
modelds.pyにモデルの定義を行います。今回はTodo件名を格納するモデルとそれから外部参照されるカテゴリーと優先度のモデルを実装しました。
# -*- coding: utf-8 -*- from django.db import models class Category(models.Model): name = models.CharField(max_length=64, unique=True) class Priority(models.Model): name = models.CharField(max_length=64, unique=True) class Todo(models.Model): title = models.CharField(max_length=200) description = models.TextField(blank=True, max_length=4000) datetime_created = models.DateTimeField(auto_now_add=True) is_finished = models.BooleanField(default=False) priority=models.ForeignKey(Priority) category=models.ForeignKey(Category)
これで管理スクリプトでDB同期(syncdb)を実行します。
#python ./manage.py syncdb
この結果データベース上に対応するテーブルが生成されます。
次の管理スクリプトで対話shellを実行して、いくつかデータを登録してみます。
$./manage.py shell Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17) [GCC 4.0.1 (Apple Inc. build 5465)] on darwin Type "help", "copyright", "credits" or "license" for more information. (InteractiveConsole) >>> >>> >>> from djsite.todo.models import Category >>> from djsite.todo.models import Priority >>> c = Category() >>> c.name = 'Private' >>> c.save() >>> c = Category() >>> c.name = 'Public' >>> c.save() >>> c = Category() >>> c.name = 'Private' >>> c.save() >>> c = Category() >>> c.name = 'Public' >>> c.save() >>> p = Priority() >>> p.name = u'now' >>> p.save() >>> p = Priority() >>> p.name = u'soon' >>> p.save() >>> p = Priority() >>> p.name = u'later' >>> p.save() >>> from djsite.todo.models import Todo >>> t = Todo() >>> t.title = u'dinner' >>> t.description = u'Dinner with moomin' >>> t.category = 1 Traceback (most recent call last): File "<console>", line 1, in <module> File "/Library/Python/2.5/site-packages/django/db/models/fields/related.py", line 264, in __set__ self.field.name, self.field.rel.to._meta.object_name)) ValueError: Cannot assign "1": "Todo.category" must be a "Category" instance. >>> t.category_id = 1 >>> t.priority_id = 2 >>> t.save <bound method Todo.save of <Todo: Todo object>> >>> t.save()
それから登録したデータをいくつか検索してみます。
>>> a = Category.objects.all() >>> a [<Category: Category object>, <Category: Category object>] >>> a[0].name u'Private' >>> a[1].name u'Public' >>> >> t = Todo.objects.get(id=1) >>> t.title u'launch'
検索フォームの実装
# -*- coding: utf-8 -*- from django import forms from djsite.todo.models import Category class TodoSearchForm(forms.Form): class CategoryModelChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): return obj.name title = forms.CharField(max_length=100, label=u'タイトル', required=False) category = CategoryModelChoiceField(Category.objects.all(), required=False,label=u'カテゴリー') include_finished = forms.BooleanField(required=False, label=u'完了分も含める')
Viewの生成
from django.http import HttpResponse from django.shortcuts import render_to_response from djsite.todo.models import Todo from djsite.todo.forms import TodoSearchForm # Create your views here. def show_list(request): """docstring for show_list""" form = TodoSearchForm(request.GET) queryset = Todo.objects.all() if form.is_valid(): cleaned = form.clean() title = cleaned['title'] category = cleaned['category'] finished = cleaned['include_finished'] if category: queryset = queryset.filter(category=category) if title: queryset = queryset.filter(title=title) if finished: queryset = queryset.filter(is_finished=True) return render_to_response('list_todo.html', dict(todos=queryset,form=form))
-
- モデルのobjects.all()で全件を返すための検索セットが返されますが、それに対してfilterメソッドをかけていき条件の絞り込みを行います。
- 送信パラメータのコレクションを指定してフォームを生成します。そのフォームのインスタンスにclean()メソッドをかけるとフォームの値のディクショナリが返されます。
- テンプレートファイル名とテンプレートに渡す変数のディクショナリを引数の指定してrender_to_responseメソッドを実行。クライアントへの送信、表示を行います。
Urlパターンの追加
プロジェクトのurls.pyにurlパターンを定義します。
from django.conf.urls.defaults import * urlpatterns = patterns('djsite.todo.views', (r'^list$','show_list'), # Example: # (r'^djsite/', include('djsite.foo.urls')), # Uncomment the admin/doc line below and add 'django.contrib.admindocs' # to INSTALLED_APPS to enable admin documentation: # (r'^admin/doc/', include('django.contrib.admindocs.urls')), # Uncomment the next line to enable the admin: # (r'^admin/(.*)', admin.site.root), )
-
- pattersの最初のパラメータ'djsite.todo.views'がそれ以降のパターンの対象とするアプリケーションの指定です。
- pattersの2つ目以降のパラメータはurlパターンとViewのメソッドの組み合わせです。今回の(r'^list$','show_list')は「http://<ホスト>/list」とリクエストされた場合,views.pyに定義されたshow_listが実行されるよう定義しました。
テンプレート
まず、テンプレートファイルをおくディレクトリをプロジェクトのsettings.pyに定義します。
TEMPLATE_DIRS = ( '/Users/nyaago/workspace/djsite/todo/templates' # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. )
表示するテンプレートを作成。settings.pyのTEMPLATE_DIRSで指定した場所に、views.pyのrender_to_responseの呼び出しパラメータで指定した名前で作成します。
<html> <head> </head> <body> <form action="./list" method="GET"> <table>{{form}}</table> <input type="submit"> </form> <table> <tr> <td>タイトル </td> <td>内容 </td> <td>カテゴリ </td> <td>優先度 </td> <td>日付 </td> </tr> {% for todo in todos %} <td>{{todo.title}} </td> <td>{{todo.description}} </td> <td>{{todo.category.name}} </td> <td>{{todo.priority.name}} </td> <td>{{todo.datetime_created|date:"Y年m月d日 H時i分"}} </td> {% endfor %} </table> </body> </html>
これで、とりあえず一覧表示されました。データも1件入れただけなので、おもしろくもなんともないですが。。
TODO
-
- ユーザ認証と認証ユーザで絞りこんだ検索
- TODOの登録、編集機能の実装