Class Based Viewのシンプルな実装「Django Vanilla Views」

Django Vanilla Views - Beautifully simple class based views


DjangoのClass-Based-Viewは継承関係が複雑で、ちょっとソースを見てフックポイントを確認したいっていうときに結構めんどくさい。

Django Vanilla Viewsは機能はそのままで実装をシンプルにして使いやすくしたもの。

図を見ると、○○Mixinがなくなり、継承関係が浅くなっているのがわかる。


適当なサンプルを作って動きを比べてみた。
以下のコードでClassBasedViewを使った一覧表示、新規登録、更新、削除ができる。

models.py

from django.db import models


class Person(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name

views.py

from django.http import HttpResponse
from django.core.urlresolvers import reverse_lazy
#from django.views.generic import CreateView, ListView, UpdateView, DeleteView
from vanilla import CreateView, ListView, UpdateView, DeleteView
from apps.models import Person


class PersonListView(ListView):
    model = Person


class PersonCreateView(CreateView):
    model = Person
    success_url = reverse_lazy('person:list')


class PersonUpdateView(UpdateView):
    model = Person
    success_url = reverse_lazy('person:list')


class PersonDeleteView(DeleteView):
    model = Person
    success_url = reverse_lazy('person:list')

urls.py

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

urlpatterns = patterns('',
                       url('^person/', include('apps.urls', namespace='person')))

apps/urls.py

# coding=utf-8
from django.conf.urls import patterns, url
from .views import PersonDetailView, PersonListView, PersonCreateView, PersonUpdateView, PersonDeleteView

urlpatterns = patterns('',
                       url(r'^$', PersonListView.as_view(), name='list'),
                       url(r'^new$', PersonCreateView.as_view(), name='new'),
                       url(r'^edit/(?P<pk>\d+)$', PersonUpdateView.as_view(), name='edit'),
                       url(r'^delete/(?P<pk>\d+)$', PersonDeleteView.as_view(), name='delete'))

person_list.html

<h1>persons</h1>
<ul>
    {% for person in object_list %}
        <li>{{ person }} :
            <a href="{% url "person:edit" person.id %}">edit</a>
            <a href="{% url "person:delete" person.id %}">delete</a>
        </li>
    {% endfor %}
</ul>

<a href="{% url 'person:new' %}">New</a>


person_form.html

<form method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Submit"/>
</form>

person_confirm_delete.html

<form method="post">{% csrf_token %}
    Are you sure you want to delete "{{ object }}" ?
    <input type="submit" value="Submit"/>
</form>


ClassBasedViewをvanillaモジュール、django.views.genericモジュールで入れ替えても挙動は全く同じになる