web-dev-qa-db-ja.com

Djangoフィルターバックエンド

私はDjango残りのフレームワークAPIを使用しています。first_nameまたはlast_nameまたはその両方でフィルターを作成しようとしています。これが私のContactViewSet.pyです。 :

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    filter_backends = (DjangoFilterBackend, )
    filter_fields = ('first_name', 'last_name')
    lookup_field = 'idContact'

DRFの設定:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('Django_filters.rest_framework.DjangoFilterBackend',),
}

私のactuelリクエストURLは次のようになります:

http://localhost:8000/api/v1/contacts/?first_name=Clair&last_name=Test

しかし、私はこのようなものを探しています:

http://localhost:8000/api/v1/contacts/?first_name=Cl**&last_name=Tes**

任意の助けをいただければ幸いです。

7
Naella

クラスContactFilterを次のように変更して問題を解決しました。

import Django_filters
from .models import Contact

class ContactFilter(Django_filters.FilterSet):
   class Meta:
        model = Contact
        fields = {
            'first_name': ['startswith'],
            'last_name': ['startswith'],
        }
        together = ['first_name', 'last_name']

そして私の見解では、私はこれをしなければなりませんでした:

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    filter_class = ContactFilter

私のリクエストURLは次のようになります:

http://localhost:8000/api/v1/contact/?first_name__contains=Cl&last_name__contains=Tes

しかし、私はまだDjangoでこのようなものができるかどうか疑問に思っています

http://localhost:8000/api/v1/contacts/?first_name=Cl**&last_name=Tes**
4
Naella

私がすることは、カスタムFilterBackendを書くことです。このようなもの:

# views.py
from rest_framework import filters

class ObjektFilterBackend(filters.BaseFilterBackend):
    allowed_fields = ['objekt', 'naziv', 'kategorija', 'zadnja_sprememba']

    def filter_queryset(self, request, queryset, view):
        flt = {}
        for param in request.query_params:
            for fld in self.allowed_fields:
                if param.startswith(fld):
                    flt[param] = request.query_params[param]

        return queryset.filter(**flt)


class ObjektiViewSet(mixins.ListModelMixin,
                 mixins.RetrieveModelMixin,
                 viewsets.GenericViewSet):
    authentication_classes = (
        authentication.TokenAuthentication,
        authentication.SessionAuthentication)
    permission_classes = (IsAuthenticated,)
    queryset = models.Objekt.objects.all()
    serializer_class = serializers.ObjektSerializer
    filter_backends = (ObjektFilterBackend, ObjektOrderBackend,)
    ....

基本的なフィルタリング(fi​​eldname = valueのペア)の他に、次のようなURLで任意の Django queryset Field Lookups (__gt、__gte、__startswith、...)を使用できます。

http://localhost:8000/api/v2/objekti/?naziv__startswith=Apartma&zadnja_sprememba__gte=2018-01-01

また、ObjektFilterBackendクラスは、パターンによる検索をサポートするように簡単に調整できます。

ほんの少しの警告-この方法はエンドユーザーが外部キーフィールドでもフィルタリングできるため、潜在的に危険です。このようなものも機能します:

http://localhost:8000/api/v2/objekti/?kategorija__naziv__icontains=sobe

したがって、allowed_fieldsを慎重に制限し、関連するユーザーモデルにつながる可能性のある外部キーを含めないでください。

2
Robert Kovac

DjangoFilterBackendは、主に等価ベースのフィルタリングだと思います。ただし、 フィルタリング方法をカスタマイズする はできます。

また、DRFでは、厳密でないフィルタリングのために、デフォルトで大文字と小文字を区別しない部分一致検索を行う SearchFilter があります。

2
Nadège

あいまい検索ルックアップでは、このアプローチを使用することをお勧めします。

filters.py

from Django_filters import rest_framework as filters
from Django.db.models import Q
from . import models

def filter_name(queryset, name, value):
    """
    Split the filter value into separate search terms and construct a set of queries from this. The set of queries
    includes an icontains lookup for the lookup fields for each of the search terms. The set of queries is then joined
    with the OR operator.
    """
    lookups = [name + '__icontains', ]

    or_queries = []

    search_terms = value.split()

    for search_term in search_terms:
        or_queries += [Q(**{lookup: search_term}) for lookup in lookups]

    return queryset.filter(reduce(operator.or_, or_queries))


class ContactFilter(filters.FilterSet):
    first_name = filters.CharFilter(method=filter_name, name='first_name')
    last_name = filters.CharFilter(method=filter_name, name='last_name')

    class Meta:
        model = models.Contact
        fields = [
            'first_name',
            'last_name',
        ]

api.py

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    filter_class = ContactFilter
    ...
1
saran3h

リクエストがそれほど複雑でない場合は、次の方法も使用できます。

class YourModelViewSet(viewsets.ModelViewSet):
    queryset = YourModel.objects.all()
    serializer_class = YourModelSerializer
    filter_fields = {'some_field': ['startswith']}

リクエストクエリパラメータで '?some_field__starswith = text'構文のサポートを有効にするものはどれですか。

「startswith」は、Django standart queryset filter param。

0
validname