[英]Filtering against query parameters Django REST Framework, Many to Many
我正在嘗試構建某種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"}
},
]
}
]
回應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"}
}
]
}
]
嘗試使用prefetch_related
過濾相關數據:
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
:
class MyModelSerializer(serializers.ModelSerializer):
data = SerializerMethodField()
class Meta:
model = MyModel
fields = ('country', 'data',)
def get_data(self, obj):
names = self.context['request'].query_params.get('Simon', None)
data = MyData.objects.filter(name__in=names.split(','))
data_serializer = MyDataSerializer(data, many=True)
return data_serializer.data
我認為我們可以使用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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.