[英]Django rest framework serialize filtered Foreign keys
class ModelA(models.Model):
views = models.PositiveBigIntegerField()
class ModelB(models.Model):
parent = models.ForeignKey(ModelA, on_delete=models.CASCADE, related_name='modelB', blank=True, null=True)
string = models.CharField()
class ModelAListView(generics.ListAPIView):
serializer_class = ModelASerialezer
queryset = ModelA.objects.all().prefetch_related('modelb')
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset.filter(modelb__string__icontains=request.GET['string']), many=True)
return Response(serializer.data)
class ModelASerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField()
modelB = ModelBSerializer(source='modelB', many=True, read_only=False)
class Meta:
model = ModelA
exclude = ('views',)
class ModelBSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = ModelB
fields = '__all__'
If I need to search by "string" field I can write如果我需要按“字符串”字段搜索,我可以写
modelA.objects.filter(modelB__string__icontains=request.GET['string']).values('modelB__string')
Which return ModelB instances only with necessary string
values :仅返回带有必要
string
值的ModelB 实例:
<QuerySet [{'modelB__string': 'Test1'}]>
When I filter by modelb_string I expect to get only filtered FK value:当我按 modelb_string 过滤时,我希望只得到过滤的 FK 值:
{
"id": 1,
"views": 0,
"modelb": [
{
"id": 46,
"string": "Test1",
"item": 1
}
]
}
but I get all FK values:但我得到了所有 FK 值:
{
"id": 1,
"views": 0,
"modelb": [
{
"id": 46,
"string": "Test1",
"item": 1
},
{
"id": 47,
"string": "Test85",
"item": 1
},
{
"id": 48,
"string": "Test64",
"item": 1
}
]
}
Few points worth mentioning :值得一提的几点:
You don't need to implement the list
function and redo what's already being done in the mixin你不需要实现
list
函数并重做mixin 中已经完成的操作
If we want to customise the queryset then we should override the get_queryset
, details如果我们想自定义查询集,那么我们应该覆盖
get_queryset
, details
Something like this :像这样的事情:
class ModelAListView(generics.ListAPIView):
serializer_class = ModelASerialezer
def get_queryset(self, *args, **kwargs):
queryset = modelA.objects.all()
given_string = self.request.query_params.get('string', None)
if given_string is not None:
queryset = queryset.filter(modelB__string__icontains=given_string)
return queryset
string
string
References :参考 :
The best practice would be on your view class最佳实践是在您的视图类中
from django.db.models import Prefetch
modelA.objects.all().prefetch_related(Prefetch(modelB, queryset=modelB.objects.filter(string__icontains=request.GET['string'])))
This returns modelA objects with filtered modelB FK related instances这将返回带有过滤的 modelB FK 相关实例的 modelA 对象
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.