汎用ビューによる更新・削除ページ

前回で、TODOタスクの追加と一覧までは実現できたので、今回からは編集と削除処理を作っていきます。

削除処理については、汎用ビューのdjango.views.generic.create_update.delete_objectを使います。利用手順としては、まず、views.pyに削除処理用のメソッドを追加します。

/todo/views.py

from django.views.generic.create_update import delete_object

def delete_task(request):
    if not request.user.is_authenticated():
        return render_to_response(request, "login.html")

    # ログインユーザのタスクかどうかチェック
    task = Task.get(request.POST["key"])
    if (task.user != request.user):
        return HttpResponseRedirect(reverse('todo.views.list_tasks'))

    return delete_object(request, Task, object_id=request.POST["key"],
                         post_delete_redirect=reverse('todo.views.list_tasks'))

メソッド中盤でログインユーザのタスクかどうかをチェックしていますが、これがないとkeyの値さえわかれば別ユーザのTODOタスクを削除することが可能になります。

次に、urls.pyで、/todo/deleteにアクセスがあったらこのメソッドが呼ばれるようにします。

/todo/urls.py

urlpatterns = patterns('todo.views',
    (r'^$', 'list_tasks'),
    (r'^create$', 'add_task'),
    (r'^delete$', 'delete_task'),

最後に、テンプレート内に削除ボタンを設置します。

/todo/templates/task_list.html

<table>
  <tr><th>タイトル</th><th>締切</th><th>削除</th></tr>
  {% for task in object_list %}
  <tr><td>{{ task.title }}</td><td>{{ task.limit_time|date:"Y-m-d" }}</td>
  <form action="delete" method="post"><td><input type="hidden" name="key" value="{{ task.key }}"><input type="submit" value="削除"></td></form>
  {% endfor %}
</table>

これで削除機能が出来上がりました。

同じ要領で、編集機能を追加します。編集処理には、汎用ビューのdjango.views.generic.create_update.update_objectを利用します。まず、views.pyに編集用のメソッドを追加します。

/todo/views.py

from django.views.generic.create_update import update_object

def update_task(request):
    if not request.user.is_authenticated():
        return render_to_response(request, "login.html")
    
    # ログインユーザのタスクかどうかチェック
    task = None
    if (request.method == "GET"):
        task = Task.get(request.GET["key"])
    else:
        task = Task.get(request.POST["key"])
    if (task.user != request.user):
        return HttpResponseRedirect(reverse('todo.views.list_tasks'))
    
    return update_object(request, form_class=TaskForm, object_id=task.key(),
                         post_save_redirect=reverse('todo.views.list_tasks'))

ログインユーザのタスクかどうかのチェックにちょっと手間をかけていますが、基本的には削除処理と同じ流れです。

次に、urls.pyを編集し、/todo/updateにアクセスしたらこのメソッドが呼ばれるようにします。

/todo/urls.py

urlpatterns = patterns('todo.views',
    (r'^$', 'list_tasks'),
    (r'^create$', 'add_task'),
    (r'^delete$', 'delete_task'),
    (r'^update$', 'update_task'),
)

最後に、テンプレートを編集し、TODOタスクのタイトルをクリックしたら編集画面に行くようにします。

/todo/templates/task_list.html

<table>
  <tr><th>タイトル</th><th>締切</th><th>削除</th></tr>
  {% for task in object_list %}
  <tr><td><a href="update?key={{ task.key }}">{{ task.title }}</a></td><td>{{ task.limit_time|date:"Y-m-d" }}</td>
  <form action="delete" method="post"><td><input type="hidden" name="key" value="{{ task.key }}"><input type="submit" value="削除"></td></form>
  {% endfor %}
</table>

と、ここで、manage.py runserverで開発サーバを立ち上げて確認すると、編集時に"key"がないと怒られてしまいました。そうか、Formに足さないといけませんね。というわけで、フォームにkeyを追加しました。

/todo/forms.py

class TaskForm(forms.ModelForm):
    user = forms.CharField(widget=forms.HiddenInput, required=False)
    title = forms.CharField(max_length=100, required=True, label=u"タイトル", help_text=u"(必須)")
    limit_time = forms.DateTimeField(required=False, label=u"締切", help_text=u"(任意)yyyy-mm-ddの形式で入力してください")
    key = forms.CharField(widget=forms.HiddenInput, required=False)
    class Meta:
        model = Task
        exclude = ('create_time')

これで動きましたので、manage.py updateでサーバへアップしました。


おそらくこれで最低限の機能はできたと思いますので、今後は、このTODO管理機能を拡張していくことを考えます。