Django Rest Framework序列化已过滤的外键

时间:2019-07-11 07:32:16

标签: django django-rest-framework django-serializer

Models.py

from companyplots import *

fig,ax=companyFigure((2,1),(500,300))
## do your plotting here...
plt.show()

Views.py

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()

Serializers.py

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__'

仅具有必要的modelA.objects.filter(modelB__string__icontains=request.GET['string']).values('modelB__string') 值的返回的ModelB实例

string

当我按modelb_string过滤时,我希望仅获得过滤后的FK值:

<QuerySet [{'modelB__string': 'Test1'}]>

但是,我得到所有FK值:

{
    "id": 1,
    "views": 0,
    "modelb": [
        {
            "id": 46,
            "string": "Test1",
            "item": 1
        }
    ]
}

2 个答案:

答案 0 :(得分:1)

几点值得一提:

  1. 您无需实现list函数并重做mixin

  2. 中已经完成的操作
  3. 如果要自定义查询集,则应覆盖get_querysetdetails

类似这样的东西:

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
  1. 也许您应该考虑重命名string字段

参考文献:

答案 1 :(得分:0)

最佳实践是在您的视图类中

from django.db.models import Prefetch


modelA.objects.all().prefetch_related(Prefetch(modelB, queryset=modelB.objects.filter(string__icontains=request.GET['string'])))

这将返回带有过滤后的 modelB FK 相关实例的 modelA 对象