【问题标题】:Django REST framework foreign keys and filteringDjango REST框架外键和过滤
【发布时间】:2014-09-11 17:33:13
【问题描述】:

我在 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,)

我需要做什么,我想获取由特定品牌制造的所有模型。 如何使用查询参数获取具有特定外键的所有模型?我的第二个问题 - 我可以使用 queryparams 过滤结果以获取具有特定 engine_capacity 的模型吗?

一条评论:如果我可以在 url 中使用类似这样的内容来查询结果,那将是完美的:/api/models/?make=ford where make is slug field in Make model

【问题讨论】:

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


    【解决方案1】:

    您可以在视图集中指定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(field_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 应该可以工作。

    【讨论】:

    • 我尝试使用您的解决方案,该解决方案看起来简单明了,但 name 参数一直给我错误。
    • 如果您指的是django_filters.ModelsChoiceFilter(name="make_slug") 中的name 属性,那么它应该是“field_name”。自从发布了我的原始答案以来,它在django_filters 的最新版本中被重命名。我会更新我的答案。
    【解决方案2】:

    扩展@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

    【讨论】:

      【解决方案3】:

      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 过滤,但恕我直言,这看起来更好。

      【讨论】:

        【解决方案4】:

        在你的视图中你需要做的事情是这样的: 它被称为“跨越关系的查找”

        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

        【讨论】:

        • 我知道如何查询标准 Django 模型,我需要对 Django Rest Framework 做同样的事情
        猜你喜欢
        • 1970-01-01
        • 2022-09-26
        • 2012-12-24
        • 2017-05-27
        • 2014-02-17
        • 2019-03-24
        • 2017-03-27
        • 2021-12-09
        相关资源
        最近更新 更多