Django rest framework сериализует отфильтрованные внешние ключи - PullRequest
1 голос
/ 11 июля 2019

Models.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

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

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

Если мне нужно выполнить поиск по полю "строка" Iможет написать

modelA.objects.filter(modelB__string__icontains=request.GET['string']).values('modelB__string')

которые возвращают экземпляры ModelB только с необходимыми string значениями :

<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
        }
    ]
}

1 Ответ

1 голос
/ 11 июля 2019

Несколько моментов, заслуживающих упоминания:

  1. Вам не нужно реализовывать функцию list и повторять то, что уже делается в mixin

  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

Рекомендации:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...