How can I serialize filtred FK values.

31 views
Skip to first unread message

Василий Русин

unread,
Jul 11, 2019, 5:41:34 AM7/11/19
to Django REST framework

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


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:
<QuerySet [{'modelB__string': 'Test1'}]>


When I filter by modelb_string I expect to get only filtered FK value:
{
   
"id": 1,
   
"views": 0,
   
"modelb": [
       
{
           
"id": 46,
           
"string": "Test1",
           
"item": 1
       
}
   
]
}


but I get all FK values:
{
   
"id": 1,
   
"views": 0,
   
"modelb": [
       
{
           
"id": 46,
           
"string": "Test1",
           
"item": 1
       
},
       
{
           
"id": 47,
           
"string": "Test85",
           
"item": 1
       
},
       
{
           
"id": 48,
           
"string": "Test64",
           
"item": 1
       
}
   
]
}


Clara Daia

unread,
Jul 11, 2019, 9:45:32 AM7/11/19
to django-res...@googlegroups.com
Such a filter will actually select every instance of ModelA with at least one related instance of ModelB which matches your filter. The filter will not exclude, in the resulting queryset, the related instances of ModelB that do not match the filter.

--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-rest-framework/e18c0ced-b487-4c03-b832-570f68b98d8e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Василий Русин

unread,
Jul 11, 2019, 10:17:03 AM7/11/19
to Django REST framework
Hm, ok, but .values() return only one FK. It's exactly the kind of behaviour that I would like to get. .values can return only one FK, so I hoped what exists any solution for this problem.

четверг, 11 июля 2019 г., 20:45:32 UTC+7 пользователь Clara Daia написал:
Такой фильтр фактически выберет каждый экземпляр ModelA, по крайней мере, с  одним связанным экземпляром ModelB, который соответствует вашему фильтру. Фильтр не исключит в результирующем наборе запросов связанные экземпляры ModelB, которые не соответствуют фильтру.

В четверг, 11 июля 2019 года в 06:41 Василий Русин < rus ... @ gmail.com > написал:
Если мне нужно искать по полю "строка", я могу написать:
modelA.objects.filter(modelB__string__icontains=request.GET['string']).values('modelB__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
       
}
   
]
}


-
Вы получили это сообщение, потому что вы подписаны на группу Google "Django REST framework".
Чтобы отписаться от этой группы и прекратить получать электронные письма от нее, отправьте электронное письмо по адресу django-rest-framework + unsub...@googlegroups.com .
Чтобы просмотреть это обсуждение в Интернете, посетите https://groups.google.com/d/ msgid / django-rest-framework / e18c0ced-b487-4c03-b832- 570f68b98d8e% 40googlegroups. ком .
Для получения дополнительной информации посетите страницу https://groups.google.com/d/ optout .

Gonzalo Amadio

unread,
Jul 11, 2019, 8:56:20 PM7/11/19
to Django REST framework
You need to make another filter.
With the one you have.. you obtained the ok you want to obtain.

Then you need to filter modelB where pk are in that first filter you made

--
You received this message because you are subscribed to the Google Groups "Django REST framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-fram...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages