12.Djangoに検索フォームを追加してみよう

Djangoアプリケーションに検索フォームを追加してみましょう。Djangoでは予め用意されているフォームクラスを継承することで、簡単にフォームを作成・表示することができます。

目次

検索フォームのクラスを定義(forms.py)

まずは今回追加する検索フォームのデータ形式を定義しましょう。

/bbs/ の下にforms.pyを作成します。

forms.pyを作成

次のように記述します。

from django import forms # Djangoのformsモジュールをインポート

# SearchFormクラスを定義
class SearchForm(forms.Form):
        keyword = forms.CharField(label='', max_length=50)

Djangoが予め用意してくれている formsモジュールをインポートし、Formクラスを継承した SearchFormクラスを定義します。

検索フォームなのでデータ型は CharField 、最大文字数は50もあれば十分でしょう。

フォームオブジェクトの追加とデータの処理(views.py)

次に views.py の index関数に 受け取ったデータの処理とフォームオブジェクトをテンプレートに渡すための処理を記述します。

from django.shortcuts import render,get_object_or_404
from django.http import HttpResponse
from .models import Article
from .forms import SearchForm # forms.pyからSearchFormクラスをインポート

def index(request):
    searchForm = SearchForm(request.GET)
    # searchForm変数に正常なデータがあれば
    if searchForm.is_valid():
        keyword = searchForm.cleaned_data['keyword'] # keyword変数にフォームのキーワードを代入
        articles = Article.objects.filter(content__contains=keyword) # キーワードを含むレコードをfilterメソッドで取り出し、articles変数に代入
    # それ以外の場合
    else:
        searchForm = SearchForm() # searchForm変数をSearchFormオブジェクトで上書き
        articles = Article.objects.all() # すべてのレコードを取得

    context = {
    'articles': articles,
    'searchForm': searchForm, # テンプレートに渡すために追記
    }
    return render(request, 'bbs/index.html', context)

def detail(request, id):
    article = get_object_or_404(Article, pk=id)
    context = {
        'article': article,
    }
    return render(request, 'bbs/detail.html', context)

index関数が実行された時、searchForm変数に正常なデータが入力されている場合はフォームのキーワードを受け取ってそのキーワードを含むレコードを抽出し、articles変数に代入してテンプレートに渡します。

それ以外の場合、つまり最初に投稿一覧ページにアクセスした場合などはそれらの処理を行わず、空のフォームとすべての投稿が表示されます。

テンプレートで表示(index.html)

次はテンプレートにフォームを追加します。

index.html に次のように記述します。

{% extends "./base.html" %}

{% block content %}
  <h1>Djangoで作る1行掲示板</h1>

  {% if searchForm %}<!-- searchFormがあれば -->
    <form action='{% url "bbs:index" %}' method="get"><!-- getメソッドでインデックス関数を呼び出す -->
      <div>
        {{ searchForm }}<!-- views.pyから受け取ったsearchFormを表示 -->
        <input type="submit" value="検索">
        <a href='{% url "bbs:index" %}'>クリア</a><!-- postメソッドでインデックス関数を呼び出す -->
      </div>
    </form>
  {% endif %}

  {% for article in articles %}
    <p>
      <a href="{% url "bbs:detail" article.id %}">{{ article.content }}</a>
      {{ article.user_name }}
    </p>
  {% endfor %}
{% endblock %}

searchFormがある場合のみ、GETメソッドでインデックス関数を呼び出し、検索フォームとクリアボタンを表示するよう記述しています。

この段階では index.html が呼ばれる場合常に searchForm はありますが、後ほど投稿削除機能を追加する場合にも呼び出す予定なのでこの条件分岐を入れています。

動作確認

それでは動作確認です。

Djangoコマンドを使ってサーバーを起動し、ブラウザで確認してみましょう。

http://127.0.0.1:8000/bbs にアクセスします。

投稿一覧ページに検索フォームを追加

検索フォームが表示できました。

実際に使ってみましょう。「こん」を含むデータを検索してみます。

「こん」を含むデータを検索

正常に動作しているのが確認できます。

「クリア」をクリックすると元のURLにアクセスしてすべての投稿が表示されます。

投稿一覧ページに検索フォームを追加

このようにDjangoでは予め用意されているフォームクラスを継承することで、簡単にフォームを作成・表示することができます。

このエントリーをはてなブックマークに追加

コメントを残す

頂いたコメントは一読した後表示させて頂いております。
反映まで数日かかる場合もございますがご了承下さい。