Django Logo

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

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

前提条件

  • Python : 3.6.2
  • Django : 3.0.5

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

search_fields を利用する方法

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

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

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

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

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

まず、検索条件入力用のテキストボックスのベースとなる 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 )を追加します。

Django Text Filter 2

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

{% 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]
    ...

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

Django Text Filter 3

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

最後に

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

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です