複雑な検索フォームを作る方法がわからない

ちょっと複雑な検索をDjangoでやってみたけどうまくいかない。
一応動作はするけどコードが大変なことになってる。
誰かが「勝手に添削」してくれることを期待して恥をさらしておく。 :p

モデルはこんな感じで
models.py

# -*- encoding: utf-8 -*-
from django.db import models
    
class Publisher(models.Model):
    name = models.CharField(maxlength=200)

class Author(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)

'/search/' で検索フォームの表示とフォームの受け取りをやってる
urls.py

urlpatterns += patterns('myproj.book.views',
    (r'^search/$', 'search'),
)

こんな感じ。
views.py

# -*- encoding: utf-8 -*-
from django.views.generic.list_detail import object_list
from myproj.book.models import Book
from django.http import HttpResponse, Http404, HttpResponseNotAllowed
from django.shortcuts import render_to_response
from django import newforms as forms
from django.db.models import Q

def search(request):
    if request.method == 'POST':
        return HttpResponseNotAllowed(['GET'])

    # GET with query strings
    if len(request.GET) > 0: 
        book_list = Book.objects.all()
        for f in request.GET:
            vlist = request.GET.getlist(f)
            vlist = [ v for v in vlist if v ]
            if not vlist:
                continue
            if f == 'name': # a field in the same model
                book_list = book_list.filter(**{f + '__icontains': vlist[0]})
            else:
                criteria = [Q(**{f + '__id': v}) for v in vlist if v]
                criteria = reduce(lambda x, y: x|y, criteria)
                book_list = book_list.filter(criteria).distinct()
            return object_list(request, queryset=book_list, allow_empty=True)

    # No query strings. Just render search form.
    SearchBookForm = forms.form_for_model(Book)
    form = SearchBookForm()
    return render_to_response('book/search.html', {'form': form})

一応動作するけど、深めにネストしてて可読性もかなり低い。
Q object使い方がいまいちよくわかっていない気が。
検索フォームの表示にforms.form_for_model(Book)なフォームをそのまま表示してるのも変。
form_for_model使わないで検索フォームを自分で定義しておく方がいいのかな。