プログラミング

[Django]管理サイトに絞り込みのテキストボックスを追加する

プログラミング
この記事は約6分で読めます。
スポンサーリンク

Djangoの管理サイトを構築するときに「search_fields」を使用してテキストボックスで検索条件を入力できるようにしているのですが、これだと一見するとどのフィールドで絞り込みを行っているのかが分からないので、今回は複数のテキストボックスの検索条件入力欄を作成し、どのフィールドで検索しようとしているのかを分かりやすくしてみようと思います。

スポンサーリンク

前提条件

  • Python:3.6.2
  • Django:3.0.5

こちらのソースをベースに実装していきたいと思います。

koichi-ezato/sample
Contribute to koichi-ezato/sample development by creating an account on GitHub.

search_fieldsを利用する方法

Djangoの管理サイトでは「search_fields」を設定することでテキストボックスで検索できるようにすることができます。

@admin.register(User)
class UserAdmin(ExportMixin, admin.ModelAdmin):
    ...
    search_fields = ['name', 'email']
    ...

検索条件を入力するテキストボックスが表示されるようになります。

ただ、これだとぱっと見て検索対象のフィールドがどれなのかが分かりません。

検索条件入力用のテキストボックスを複数作成する

まず、検索条件入力用のテキストボックスのベースとなるInputFilterクラスを作成します。このクラスがテキストボックスの部品のベースとなります。

class InputFilter(admin.SimpleListFilter):
    template = 'admin/input_filter.html'

    def lookups(self, request, model_admin):
        # Dummy, required to show the filter.
        return ((),)

    def choices(self, changelist):
        # Grab only the "all" option.
        all_choice = next(super().choices(changelist))
        all_choice['query_parts'] = (
            (k, v)
            for k, v in changelist.get_filters_params().items()
            if k != self.parameter_name
        )
        yield all_choice

次にテンプレートファイルを作成します。上記のクラスでtemplateに設定しているpathにファイル(input_filter.html)を追加します。

追加したファイルに下記のように実装します。

{% load i18n %}

<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul>
    <li>
        <form method="GET" action="">
            {% for k, v in all_choice.query_parts %}
                <input type="hidden" name="{{ k }}" value="{{ v }}" />
            {% endfor %}

            <input
                    type="text"
                    value="{{ spec.value|default_if_none:'' }}"
                    name="{{ spec.parameter_name }}"/>
        </form>
    </li>
</ul>

これで検索条件のテキストボックスのベースの部品の実装が完了しました。

それでは、それぞれのフィールドに対応したテキストボックスのフィルタを実装していきます。

# last_name
class NameFilter(InputFilter):
    parameter_name = 'last_name'
    title = '苗字'

    def queryset(self, request, queryset):
        if self.value() is not None:
            last_name = self.value()

            if last_name is None:
                return

            return queryset.filter(last_name__icontains=last_name)

# email
class EmailFilter(InputFilter):
    parameter_name = 'email'
    title = 'メールアドレス'

    def queryset(self, request, queryset):
        if self.value() is not None:
            email = self.value()

            if email is None:
                return

            return queryset.filter(email__icontains=email)

最後にUserAdminクラスのlist_filterに上記のクラスを設定します。

@admin.register(User)
class UserAdmin(ExportMixin, admin.ModelAdmin):
    ...
    list_filter = [IsActiveListFilter, NameFilter, EmailFilter]
    ...

ここまで実装できたら実際に一覧画面を確認してみます。

苗字とメールアドレスの検索条件入力用のテキストボックスが一覧の右側にあるフィルタのところに追加されました!!

最後に

システムの中身を理解している人だけが管理サイトを使用する場合は、検索ボックスは一つでも問題ないかもしれませんが、そうでない場合は、検索条件入力用のテキストボックスはフィールドごとに分かれている方が検索もしやすくなると思います。

スポンサーリンク
スポンサーリンク
KoEをフォローする
CodeLab

コメント

タイトルとURLをコピーしました