前回の記事のコードをベースに解説する。
■Formクラス
以下のようにFormクラスを継承して、ArticleSearchFormクラスを生成する。
# -*- coding: utf-8 -*- from django import forms class ArticleSearchForm(forms.Form): word = forms.CharField()
■ビュー関数
以下のようにsearch関数を定義する。
from django.http import HttpResponse from django.http import Http404 from django.template import Context, loader, RequestContext from models import Article from forms import ArticleSearchForm # Create your views here. def article(request, id): try: article = Article.objects.get(id = id) tpl = loader.get_template('page/article.html') context = Context({'article' : article}) return HttpResponse(tpl.render(context)) except Article.DoesNotExist: raise Http404 def search(request): if request.method == 'POST': form = ArticleSearchForm(request.POST) if form.is_valid(): tpl = loader.get_template('page/search.html') articles = Article.objects.filter(title = form.cleaned_data['word']) return HttpResponse(tpl.render(RequestContext( request, { 'form' : form, 'articles' : articles } ))) else: form = ArticleSearchForm() tpl = loader.get_template('page/search.html') return HttpResponse(tpl.render(RequestContext( request, { 'form' : form } )))
この場合、タイトルが完全一致しないと検索にヒットしないので以下のように__containsを付加する。これはSQLでいうLIKEのような役割だ。
from django.http import HttpResponse from django.http import Http404 from django.template import Context, loader, RequestContext from models import Article from forms import ArticleSearchForm # Create your views here. def article(request, id): try: article = Article.objects.get(id = id) tpl = loader.get_template('page/article.html') context = Context({'article' : article}) return HttpResponse(tpl.render(context)) except Article.DoesNotExist: raise Http404 def search(request): if request.method == 'POST': form = ArticleSearchForm(request.POST) if form.is_valid(): tpl = loader.get_template('page/search.html') articles = Article.objects.filter(title__contains = form.cleaned_data['word']) return HttpResponse(tpl.render(RequestContext( request, { 'form' : form, 'articles' : articles } ))) else: form = ArticleSearchForm() tpl = loader.get_template('page/search.html') return HttpResponse(tpl.render(RequestContext( request, { 'form' : form } )))
更に、条件をORで結合させたい場合は以下のようにする。
from django.http import HttpResponse from django.http import Http404 from django.template import Context, loader, RequestContext from models import Article from forms import ArticleSearchForm from django.db.models import Q # Create your views here. def article(request, id): try: article = Article.objects.get(id = id) tpl = loader.get_template('page/article.html') context = Context({'article' : article}) return HttpResponse(tpl.render(context)) except Article.DoesNotExist: raise Http404 def search(request): if request.method == 'POST': form = ArticleSearchForm(request.POST) if form.is_valid(): tpl = loader.get_template('page/search.html') word = form.cleaned_data['word'] articles = Article.objects.filter(Q(title__contains = word) | Q(content__contains = word)) return HttpResponse(tpl.render(RequestContext( request, { 'form' : form, 'articles' : articles } ))) else: form = ArticleSearchForm() tpl = loader.get_template('page/search.html') return HttpResponse(tpl.render(RequestContext( request, { 'form' : form } )))
この辺はZendの方がSQLチックで直感的な気がする。
■テンプレート
以下のようにテンプレートを記述する。
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>search</title> <head> <body> <p>{{error_msg}}</p> <form action="/search/" method="POST"> {% csrf_token %} {{form.word}} <input type="submit" value="search"> </form> <br> <table> <tr> <th>title</th> <th>date</th> </tr> {% for article in articles %} <tr> <td>{{article.title}}</td> <td>{{article.date}}</td> </tr> {% endfor %} </table> </body> </html>
「setting.pyのMIDDLEWARE_CLASSESにdjango.middleware.csrf.CsrfViewMiddlewareが含まれている」かつ「ビュー関数でRequestContextを使用している」場合、{% csrf_token %}にCSRF対策用のトークンが埋め込まれる。
■URL設定
以下のように記述してURLを設定する。
from django.conf.urls.defaults import * # Uncomment the next two lines to enable the admin: from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', (r'^admin/', include(admin.site.urls)), (r'^article/(?P<id>[0-9]+)/$', 'dj.article.views.article'), (r'^search/$', 'dj.article.views.search'), )