简体   繁体   English

Django rest框架序列化过滤的外键

[英]Django rest framework serialize filtered Foreign keys

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

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

Serializers.py序列化器.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__'

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 :值得一提的几点:

  1. You don't need to implement the list function and redo what's already being done in the mixin你不需要实现list函数并重mixin 中已经完成的操作

  2. If we want to customise the queryset then we should override the get_queryset , details如果我们想自定义查询集,那么我们应该覆盖get_querysetdetails

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
  1. Maybe you should consider renaming the field 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM