Djangoで検索機能を作りたい。ListViewにカスタムフィルタを実装する方法と注意点

▼この記事をSNSでシェアする▼

スポンサーリンク

スポンサーリンク

Djangoで人狼の村構成を検索するアプリを作っているとんびです。

Djangoを始めて1ヶ月のど初心者なりに、簡単な検索機能を実装したのでそのときつまづいたところとかポイントをまとめていきたいと思います。

これがベストなのかわかりませんし、コードも綺麗ではないと思うんですが、すこしでもお役に立てればと思い備忘録として残してます。

アドバイスあればTwitterとかでもらいたいですw

@tonbi00080

1. 利用している環境

おさらいしておきましょう。

Mac OS High Sierra10.13.6に下記のものを利用しています。

  • Atom(テキストエディタ+ターミナル付き)
  • Homebrew(パッケージマネージャ)
  • Python3(version 3.7.0)と主要なライブラリ(numpy,matplotlib,scipy,pandas)
  • Bootstrap 4.1.1を適用しています。
  • 作成中のjinromuraアプリにはtemplateのindex.html(ListView)とdetail.html(detail.view)を汎用ビューで作成しています。

2. 検索機能の実装方法

2.1 検索機能の実装の進め方

どんなイメージで実装するかというと、

  1. templatetags/people_filters.py:アプリのフォルダのtemplatetagsフォルダを作り、条件に合わせて結果を絞り込むカスタムフィルタを作る
  2. views.py:indexビューが呼び出された時は、デフォルトでオブジェクトのリストを一覧で表示し、getリクエストをトリガーに人数条件のフィルタが実行されるようにメソッド(get_context_data,get_queryset)を設定する
  3. index.html:入力フォームの作成、カスタムフィルタのロードしListViewを設定したのオブジェクトリストをセットする記述を書く

こんな感じです。

2.2 アプリで実現したい細かい仕様

あくまでぼくの作成しているアプリの仕様ですが、検索機能を実装する際に一般的な設定となります。

どういう場合にどういう処理をするかを整理しておきます。

  • indexされたときは、村構成をすべて一覧表示
  • 人数の条件を指定し、[表示]ボタンをクリックすると、条件に合う人数の村だけ表示される
  • 人数の条件に合う村構成ない場合は条件に該当するデータがない旨をUIに表示する
  • 人数の条件が空のときは全件表示する
  • 検索したのちに条件をUIに表示する

僕のアプリの場合

models.pyのクラスVillage(人狼の村構成)のデータ群を人数順にソートして全件、object_listに格納しています。

今回はそのオブジェクトリスト(object_list)に、人数の条件に合わせてフィルタを実装していきます。

※Modelにmodels.pyのクラスを指定することで、データのリストがListViewに標準で用意されているobject_listに代入される

3. 検索機能の実装手順

3.1 templatetags/people_filters.py

まずは人数の絞り込みをおこなう組み込み用のタグを作成します。

今回models.pyで定義されているVillageのpeople属性の数字が入力値に等しいものを表示します。

カスタムフィルタでは

まとめ

3.2 views.py

generic.ListViewのget_context_dataをオーバーライドして一覧表示します。

get_context_dataはcontextを渡すメソッドとして用意されています。

参考:Generic display ビュー

→Django Document のリンクです。ListViewのメソッドについて書かれています。

<12行目>
modelにVillageを代入して人数順にソートしてobject_listに代入しています。

→index.htmlでfor文で取り出して表示する

<21−30行目>

入力フォームで受け取るpeopleという名前のinputタグ(あとで設定)から受け取った値がnullだったり、peopleが入力されていなくて””がreturnされたときは検索フィルタを実行せず、全件表示されるようにします。

→応急処置的な感じで汚い書き方になってしまってます・・・

3.3 template/index.html

<6行目>

人数で絞り込む組み込み用のタグ(people_filters.py)のロード

<16−25行目>

入力フォームを表します。
人数を入力するのでinputタグにnumberを指定して人数のみを入力するように制限をかけます。表示ボタンを成すbuttonタグとinputタグを含める形でformタグにgetメソッドを記述していきます。

GETメソッドの値取得のポイント
inputタグでvalueにrequest.GET|peopleと記述し、[表示]ボタンをクリックするとGETリクエストをトリガーにpeopleに入力値を渡す設定をします。

<28行目〜>

[表示]ボタンをクリックすると、検索条件の欄にrequest.GET|peopleを表示し、どのような条件で(〜人)検索したかを表示しています。

またif文を用いて、object_listのリストの中身がないときは「条件に該当する村は見つかりませんでした。」と表示する仕様にしています。

object_listの中身がある場合は変数villageに繰り返しリストが渡され、カード形式のオブジェクトの中に村名・難易度・人数を表示しています。

※難易度の数字を★で表記する機能もrange.pyという組み込みタグで実現しています。(今回は詳細には触れません。

4. 画面表示

実装の結果を画面で確認します。

一覧画面にアクセス           条件指定無しで検索

存在する人数のデータで検索       存在しない人数のデータで検索

最初に整理していた通りの仕様で実装できたことが確認できました!!!

5. ソースコード

たいそうなプロダクトではありませんし、デザイン未整形のアプリですが、ソースコードをgithubにて公開しています

詳細が気になる方はご参照ください。

今回の記事作成時のソースコード(jinromura)

次はpaginateでも実装しようかと考えています。

スポンサーリンク

▼この記事をSNSでシェアする▼

フォローする

メニュー・主な記事カテゴリ

おすすめ特集!




「ゆとり鳥日記」について
ITを中心に関心の赴くままに好きなように書いていく雑記ブログ!管理人が二人います。
◆フクロウ(19卒就活生)
◆トンビ(社会人1年目SE)

詳しいプロフィール
お仕事の依頼・ご要望

ゆとり鳥日記をBTCで応援する