我正在尝试构建某种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 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"}
}
]
}
]
答案 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