Django 1.4 で Class-based views 使ってみた

Django は MTV フレームワークであって、 V の関数ベースのコーディングは知っていた。

けれど、最近 Class-based view があると聞いて、よく知らないので知るために使ってみた。

環境

ディレクトリ構成
  • 適当な動作確認アプリなので、名前はごめんなさい。。。
  • settings は分けている。
  • staticfile で静的ファイルを修正して、collectstatic で static へ。 (ここら辺割と適当ですみません。)
$ tree diary
diary
├── conf
│   ├── diary.db
│   ├── __init__.py
│   ├── settings
│   │   ├── base.py
│   │   ├── conn.py
│   │   ├── dev.py
│   │   ├── __init__.py
│   │   └── prod.py
│   ├── urls.py
│   └── wsgi.py
├── diary
│   ├── forms.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── manage.py
├── static
│   └── js
│       └── main.js
├── staticfiles
│   └── js
│       └── main.js
└── templates
    └── layout.html

views.py

  • エラー時の処理は未実装。。。
  • csrf トークンは csrf_protect decorator なくても標準で入るみたい。
  • どこかで、Django に Class-based Views が入った経緯を押さえたいと書いていたのがあった。自分も知りたいけど、公式の 『Writing Web applications 〜』 からの 2段落がそれかな。
# coding: utf-8
from django.views.generic import (
    ListView,
    CreateView,
    UpdateView,
    DeleteView,
)

import diary.forms
import diary.models


class HomeView(ListView):
    """
    一覧を表示する
    """
    template_name = 'layout.html'
    context_object_name = 'comments'
    queryset = diary.models.Comment.objects.all()[:100]

    def get_context_data(self, **kwargs):
        context = super(self.__class__, self).get_context_data(**kwargs)
        # コメント用フォームを生成する
        context['comment_form'] = diary.forms.CommentForm()
        return context


class CreateCommentView(CreateView):
    """
    コメントを追加する
    """

    model = diary.models.Comment
    form_class = diary.forms.CommentForm
    success_url = '/'

class UpdateCommentView(UpdateView):
    """
    コメントを更新する
    """

    template_name = 'layout.html'
    model = diary.models.Comment
    success_url = '/'


class DeleteCommentView(DeleteView):
    """
    コメントを削除する
    """

    model = diary.models.Comment
    success_url = '/'

その他もろもろ

urls.py

update, delete は pk を入れないと対象のデータが取得できないエラーで動作せず。update、delete の各Class に get_object を実装するも、url に pk がないと動かない。

from django.conf.urls import patterns, include, url

import diary.views

# Uncomment the next two lines to enable the admin:
# from django.contrib import admin
# admin.autodiscover()

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'conf.views.home', name='home'),
    # url(r'^diary/', include('diary.foo.urls')),
    #url(r'^$', 'diary.views.home', name='home'),
    url(r'^$', diary.views.HomeView.as_view(), name='home'),
    url(r'^diary/create$',
        diary.views.CreateCommentView.as_view(), name='create_comment'),
    url(r'^diary/(?P<pk>\d+)/update$',
        diary.views.UpdateCommentView.as_view(), name='update_comment'),
    url(r'^diary/(?P<pk>\d+)/delete$',
        diary.views.DeleteCommentView.as_view(), name='delete_comment'),

    # Uncomment the admin/doc line below to enable admin documentation:
    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    # Uncomment the next line to enable the admin:
    # url(r'^admin/', include(admin.site.urls)),
)
models.py
# coding: utf-8
from datetime import datetime

from django.db import models

class CommentManager(models.Manager):
    pass

class Comment(models.Model):
    objects = CommentManager()

    name = models.CharField(
        'name',
        max_length=256)
    content = models.CharField(
        'content',
        max_length=256)
    ctime = models.DateTimeField(
        'date created',
        auto_now_add=True,
        blank=True)
    utime = models.DateTimeField(
        'date updated',
        auto_now=True,
        blank=True)

    class Meta:
        db_table = 'comment'
        # 単数形
        verbose_name = 'comment'
        # 複数形
        verbose_name_plural = 'comments'
forms.py
# coding: utf-8
from django.forms import ModelForm

import diary.models

class CommentForm(ModelForm):
    class Meta:
        model = diary.models.Comment
        fields = ('name', 'content')

参考