Django REST框架外键和过滤

时间:2014-07-21 09:03:52

标签: python django rest django-models django-rest-framework

我在django应用程序中有以下模型:

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外键的所有模型?我的第二个问题 - 我可以使用queryparams过滤结果以获得具有特定engine_capacity的模型吗?

一条评论:如果我可以在网址中使用类似的内容查询结果,那将是完美的:/api/models/?make=ford其中 make slug字段Make模型

4 个答案:

答案 0 :(得分:19)

您可以在视图集中指定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。注意双下划线符号。

Docs

如果您不喜欢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应该有用。

答案 1 :(得分:7)

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)

了解更多信息checkout the docs

你也可以使用QUERY_PARAMS过滤,但恕我直言看起来更好。

答案 2 :(得分:1)

您在视图中需要做的是这样的事情: 它被称为&#34;查找跨越关系&#34;

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 query making

答案 3 :(得分:0)

要扩展@ 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-namehttps://django-filter.readthedocs.io/en/master/ref/filters.html#to-field-name