Django REST Frameworkのdjango-filterを使って「記事タイトルのキーワード検索するためのフィルタ機能」を作ろうとしていました。

ところが上手くdjango-filterが動かず少しハマってしまいました。

最終的に今回の場合は、一箇所の記述を変えるだけで動作したのですがその時のメモです。

django-filterが動作しない原因・解決法

views内で使用フィルタを指定するfilter_classfilterset_classに変更することで動作しました。

つまり原因はこのviews内のフィルタ指定の書き方が間違っていたみたいです。

ただ、以前作成したサービスではfilter_classでも動作しているので、もしかするとバージョンによる違いなのかもしれません。

動作しなかったコード

class Blog(models.Model):
    title = models.CharField(blank=True, null=True, max_length=255, verbose_name='タイトル')
    created_at = models.DateTimeField(auto_now_add=True, blank=True, null=True, verbose_name='作成日時')
    updated_at = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name='更新日時')
# 【Blog】リスト取得View
class BlogListView(generics.ListAPIView):
    queryset = Blog.objects.all()       # 1: クエリセット
    permission_classes = (AllowAny,)    # 2: アクセス許可範囲を指定
    serializer_class = BlogSerializer   # 3: 利用するSerializer指定
    filter_class = BlogFilter           # 4: 利用するFilter指定


# 【Blog】シリアライザー
class BlogSerializer(serializers.ModelSerializer):

    class Meta:
        model = Blog
        fields = '__all__'


# 【Blog】フィルタ
class BlogFilter(serializers.ModelSerializer):
    title = filters.CharFilter(name="title", lookup_expr='contains')

    class Meta:
        model = Blog
        fields = '__all__'

修正後コード

# 【Blog】リスト取得View
class BlogListView(generics.ListAPIView):
    queryset = Blog.objects.all()       # 1: クエリセット
    permission_classes = (AllowAny,)    # 2: アクセス許可範囲を指定
    serializer_class = BlogSerializer   # 3: 利用するSerializer指定
    filterset_class = BlogFilter        # 【修正箇所】4: 利用するFilter指定


# 【Blog】シリアライザー
class BlogSerializer(serializers.ModelSerializer):

    class Meta:
        model = Blog
        fields = '__all__'


# 【Blog】フィルタ
class BlogFilter(serializers.ModelSerializer):
    title = filters.CharFilter(name="title", lookup_expr='contains')

    class Meta:
        model = Blog
        fields = '__all__'

まとめ

やっぱり常に公式ドキュメントを見る癖をつけないといけないですね。

あと他環境でfilter_classが動作して、今回は動作しなかった詳しい原因がわからないままですが、バージョン管理の重要さについても実感することができました。