Djangoでジェネリックビューの続き

via http://d.hatena.ne.jp/Voluntas/20070325/1174799784
via http://d.hatena.ne.jp/akkt/20070325/1174809264


いきなり2人からトラックバック頂いて少々焦り気味ですが。
コメントだと長くなりそうなので、こちらに書いてみます。

def search_auther(request, author_id):
    books = Book.objects.filter(authors__id=author_id)
    return list_detail.object_list(request, queryset=books)
汎用ビュー - Twisted Mind
def author_list(request, author):
    book_list = Book.objects.filter(authors__name__exact=author)
    return object_list(request, queryset=book_list, extra_context={'author_name': author})
Generic Viewでちょっと複雑なことをする - rants

どちらも同じような感じだと思います。

  1. ビューを書いて、urls.pyでそれを指すようにする。
  2. ビューでクエリセットを取得する。
  3. 結果をジェネリックビューに渡す。

自分も最初はそう書いてました。
だんだんモデルが複雑になってきたとき、同じようなビューがたくさんあることに気付いたんですね。
同じようなコードだからまとめられるんじゃ?と思って、突き詰めていったら前回のコードができたと。
最終的には、同じようにジェネリックビューにお任せしてます。


例えば、前回のモデルを拡張してみます。

# -*- encoding: utf-8 -*-
from django.db import models

class Author(models.Model):
    name = models.CharField(maxlength=200)
    
class Publisher(models.Model):
    name = models.CharField(maxlength=200)

class Genre(models.Model):
    name = models.CharField(maxlength=200)

class Book(models.Model):
    name = models.CharField(maxlength=200)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    genres = models.ManyToManyField(Genre)


で、urls.pyはこう書けます。

urlpatterns = patterns('',
    (r'^$', 'django.views.generic.list_detail.object_list', {'queryset':Book.objects.all()}),
   (r'^(author/(?P<author_id>\d+)/)?(publisher/(?P<publisher_id>\d+)/)?(genre/(?P<genre_id>\d+)/)?$',
        'djangotest.book.urls.lookup', {
            'allow_empty' : True,
            'paginate_by' : 10,
            'filters' : {
                'author_id' : 'authors__id' ,
                'publisher_id' : 'publisher__id',
                'genre_id' : 'genres__id'},
            'query' : lambda x: Book.objects.filter(x) })
)


http://localhost:8000/book/
これだったら書籍一覧が表示されて、
http://localhost:8000/book/author/1/publisher/1/
これは著者IDが1で出版社IDが1の書籍一覧、
http://localhost:8000/book/publisher/1/genre/1/
これは出版社IDが1でジャンルIDが1の書籍一覧が表示されます。


と、これくらいの簡単な検索なら、追加のビューを書かずにカバーできます。
ジェネリックビューが使えないと言ってるわけではないですよー。
(URLが変態的なのは否定できませんが・・・)