web-dev-qa-db-ja.com

Django RESTフレームワークの外部キーとフィルタリング

Django app:に次のモデルがあります。

models.py

class Make(BaseModel):
    slug = models.CharField(max_length=32) #alfa-romeo
    name = models.CharField(max_length=32) #Alfa Romeo

    def __unicode__(self):
        return self.name

class Model(BaseModel):
    make = models.ForeignKey(Make)  #Alfa Romeo
    name = models.CharField(max_length=64) # line[2]
    engine_capacity = models.IntegerField()
    trim = models.CharField(max_length=128) # line[4]

そしてserializers.py

from .models import Make,Model
from rest_framework import serializers


class MakeSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Make
        fields = ('url', 'slug', 'name')


class ModelSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Model
        fields = ('url', 'make', 'name', 'trim', 'engine_capacity')

またviews.py

from rest_framework import viewsets
from rest_framework import filters
from rest_framework import generics

from .models import Make, Model
from .serializers import MakeSerializer, ModelSerializer


class MakeViewSet(viewsets.ModelViewSet):
    queryset = Make.objects.all()
    serializer_class = MakeSerializer
    filter_backends = (filters.DjangoFilterBackend,)

class ModelViewSet(viewsets.ModelViewSet):
    make = MakeSerializer
    queryset = Model.objects.all()
    serializer_class = ModelSerializer
    filter_backends = (filters.DjangoFilterBackend,)

私がする必要があるのは、特定のメーカーによって製造されたすべてのモデルをフェッチしたいです。クエリパラメータを使用して、特定のmake外部キーを持つすべてのモデルを取得するにはどうすればよいですか?そして私の2番目の質問-queryparamsを使用して結果をフィルタリングし、特定のengine_capacityを持つモデルを取得できますか?

1つのコメント:URLで次のようなものを使用して結果をクエリできる場合は完璧です:/api/models/?make=fordここで、makeslugモデルのMakeフィールドです

16
dease

urls.py

url('^model/by/(?P<make>\w+)/$', ModelByMakerList.as_view()),

views.py

class ModelByMakerList(generics.ListAPIView):
    serializer_class = ModelSerializer

    def get_queryset(self):
        """
        This view should return a list of all models by
        the maker passed in the URL
        """
        maker = self.kwargs['make']
        return Model.objects.filter(make=maker)

詳細については ドキュメントを確認してください

QUERY_PARAMSでフィルタリングを使用することもできますが、私見ではこれの方が見栄えがします。

11
danielcorreia

ビューセットでfilter_fields = ('make__slug', )を指定できます。 filter_backends = (DjangoFilterBackend, )も含めることを忘れないでください。また、Django-filter依存関係を追加する必要があります。

class ModelViewSet(viewsets.ModelViewSet):
    queryset = Model.objects.all()
    serializer_class = ModelSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('make__slug',)

次に、/api/models/?make__slug=fordのようにクエリを実行します。二重下線記号に注意してください。

ドキュメント

URLのmake__slugキーワード引数が気に入らない場合は、フィルタークラスを作成できます。

import Django_filters

from myapp.models import Make


class ModelFilter(Django_filters.FilterSet):
    make = Django_filters.ModelChoiceFilter(name="make__slug",
                                            queryset=Make.objects.all())

    class Meta:
        model = Model
        fields = ('make',)

その後

class ModelViewSet(viewsets.ModelViewSet):
    make = MakeSerializer
    queryset = Model.objects.all()
    serializer_class = ModelSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = ModelFilter

/api/models/?make=fordは機能するはずです。

29

あなたの見解であなたがする必要があるのはこのようなものです:それは「関係にまたがるルックアップ」と呼ばれます

queryset = Model.objects.filter(make__name__exact='Alfa Romeo')

特定のエンジン容量を持つモデルのフィルタリングは類似しています

queryset = Model.objects.filter(engine_capacity__exact=5)

両方のフィルターを組み合わせたい場合は、それらを連鎖させることができます。

queryset = Model.objects.filter(make__name__exact='Alfa Romeo').filter(engine_capacity__exact=5)

その他の例はここにあります Djangoクエリ作成

1
AHaberl

@ vladimir-prudnikovの answer を拡張するには:

最近のバージョンのDjango-filterでは状況が少し変わりました。あなたはおそらく欲しいです:

class ModelFilter(Django_filters.FilterSet):
    make = Django_filters.ModelChoiceFilter(field_name='make__slug',
                                            to_field_name='slug',
                                            queryset=Make.objects.all())

    class Meta:
        model = Model
        fields = ('make',)

https://Django-filter.readthedocs.io/en/master/ref/filters.html#field-name および https://Django-filter.readthedocs.io/ en/master/ref/filters.html#to-field-name

1
felixhummel