过滤查询参数Django REST Framework,多对多

时间:2018-02-18 13:14:30

标签: python django django-rest-framework filtering django-queryset

我正在尝试构建某种API,但我需要过滤URL中的查询参数请求(http:// ... /?arg1 = foo1& arg2 = foo2& ...)。在我的模型方案中,我使用了多对多的关系。以下是我的一些代码:

程序my_app / models.py

from django.contrib.postgres.fields import JSONField
from django.db import models


class MyData(models.Model):
    name = models.CharField(max_length=20)
    values = JSONField()


class MyModel(models.Model):
    time = models.DateTimeField()
    country = models.CharField(max_length=50)
    data = models.ManyToManyField(MyData)

程序my_app / serializers.py

from rest_framework import serializers
from my_app.models import MyModel, MyData


class MyDataSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyData
        fields = ('name', 'values',)


class MyModelSerializer(serializers.ModelSerializer):
    data = MyDataSerializer(many=True, read_only=True)

    class Meta:
        model = MyModel
        fields = ('country', 'data',)

程序my_app / views.py

from rest_framework import generics
from my_app.serializers import MySerializer
from my_app.models import MyModel


class MyView(generics.ListAPIView):
    serializer_class = MySerializer

    def get_queryset(self):
        queryset = MyModel.objects.all()
        names = self.request.query_params.get('Simon', None)
        if names:
            queryset = queryset.filter(data__name__in=names.split(','))
        return queryset

以下是回复

http://127.0.0.1:8000/hello/

的回应
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "country": "Spain",
        "data": [
            {
                "name": "Mark",
                "values": {"A": "Hello, it's Wario"}
            },
            {
                "name": "Simon",
                "values": {"A": "Hello, it's Mario"}
            },
        ]
    },

    {
        "country": "Italy",
        "data": [
            {
                "name": "Jake",
                "values": {"A": "Hello, it's Luigi"}
            }
        ]
    }
]

http://127.0.0.1:8000/hello/?name=Simon

的回应
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "country": "Spain",
        "data": [
            {
                "name": "Mark",
                "values": {"A": "Hello, it's Wario"}
            },
            {
                "name": "Simon",
                "values": {"A": "Hello, it's Mario"}
            },
        ]
    }
]

但是当我要求时我想要获得的回复是什么?name = Simon是:

http://127.0.0.1:8000/hello/?name=Simon

的回应
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[
    {
        "country": "Spain",
        "data": [
            {
                "name": "Simon",
                "values": {"A": "Hello, it's Mario"}
            }
        ]
    }
]

2 个答案:

答案 0 :(得分:2)

我认为我们可以使用Django Filter包执行此操作。要使用此包,您需要将其安装为任何其他python包。 pip install django-filter也将为您做同样的事情。然后,您需要在项目中的任何位置定义自定义过滤器类,如下所示,

from django_filters import rest_framework as filters
from my_app.models import MyModel

class MyFilter(filters.FilterSet):
    name = filters.CharFilter(name='data__name')

    class Meta:
        model = MyModel
        fields = ['name', ]

然后您必须稍微更改views.py

from django_filters import rest_framework as filters


class MyView(generics.ListAPIView):
    serializer_class = MyModelSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = MyFilter

    def get_queryset(self):
        return MyModel.objects.all()



注意:我认为你可以使用这个很棒的软件包来定义和使用任何类型的过滤器我自定义filter class

答案 1 :(得分:1)

尝试使用prefetch_related过滤相关数据:

ClassName":"System.FormatException","Message":"Input string was not in a correct format.","Data":null,"InnerException":null,"HelpURL":null,"StackTraceString":".....

您也可以使用from django.db.models import Prefetch class MyView(generics.ListAPIView): serializer_class = MySerializer def get_queryset(self): queryset = MyModel.objects.all() names = self.request.query_params.get('Simon', None) if names: queryset = queryset.filter(data__name__in=names.split(',')).prefetch_related(Prefetch('data', queryset=MyData.objects.filter(name__in=names.split(','))) return queryset

SerializerMethodField