首页 > 解决方案 > Django rest框架序列化过滤的外键

问题描述

模型.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()

视图.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)

序列化程序.py

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

仅返回具有必要string的ModelB 实例:

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

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

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

我得到所有 FK 值:

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

标签: djangodjango-rest-frameworkdjango-serializer

解决方案


有几点值得一提:

  1. 您无需实现该功能并重做mixinlist中已经完成的工作

  2. 如果我们想自定义查询集,那么我们应该覆盖get_queryset, details

像这样的东西:

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

参考 :


推荐阅读