Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'RelatedManager' object has no attribute 'pk' in DRF Serializer

This is my (simplified) models.py:

class MyList(models.Model):
    title = models.CharField(max_length=40)
    participants = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        through='ParticipantsInList',
        related_name='participants',
    )

class ParticipantsInList(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='user')
    list_parent = models.ForeignKey(MyList, related_name='list_parent')
    moderator = models.BooleanField(default=False)

and my serializers.py:

class ParticipantsInListSerializer(serializers.ModelSerializer):

    class Meta:
        model = ParticipantsInList
        exclude = ('id',)

and my views.py:

class ParticipantsInListView(generics.ListCreateAPIView):
serializer_class = ParticipantsInListSerializer

def get_queryset(self):
    list_id = self.kwargs['list_pk']
    # This works:
    # return ParticipantsInList.objects.filter(list_parent=list_id)
    # While this doesn't:
    return MyList.objects.get(pk=list_id).participants.all()

I can't figure out why using this in views.py: ParticipantsInList.objects.filter(list_id=list_id) works, while using List.objects.get(pk=list_id).participants.all() raises an exception 'RelatedManager' object has no attribute 'pk'.

I would like to use the latter because i find it better looking and also because i believe it should work..

like image 551
Christer William Persson Avatar asked Dec 28 '15 19:12

Christer William Persson


1 Answers

The problem was that I was trying to serialize the through-model, which works if the query is run on the through-model itself (as was the case when filter was used). But when using the ManyToManyField in MyList to make the query, only the actual user object is returned. So when referencing the ManyToManyField, the solution was to use a serializer that could serialize the user object, not the through-model.

Running the queries in a shell makes this evident:

> ParticipantsInList.objects.filter(list_parent=1)
[<ParticipantsInList: ParticipantsInList object>, <ParticipantsInList: ParticipantsInList object>]

While running the other query returns:

> MyList.objects.get(pk=1).participants.all()
[<MyUser: user1>, <MyUser: user2>]
like image 112
Christer William Persson Avatar answered Oct 18 '22 12:10

Christer William Persson