Serializer with foreign keys unable to do depth when POSTing?

458 views
Skip to first unread message

Joshua Turmel

unread,
Nov 20, 2015, 11:00:13 AM11/20/15
to Django REST framework
I've got a situation where I have a model with two foreign keys on them when creating an instance need to just pass the IDs

class FriendshipRequest(models.Model):
   
""" Model to represent friendship requests """
    from_user
= models.ForeignKey(AUTH_USER_MODEL, related_name='friendship_requests_sent')
    to_user
= models.ForeignKey(AUTH_USER_MODEL, related_name='friendship_requests_received')


    message
= models.TextField(_('Message'), blank=True)


    created
= models.DateTimeField(default=timezone.now)
    rejected
= models.DateTimeField(blank=True, null=True)
    viewed
= models.DateTimeField(blank=True, null=True)

On the serializer when POSTing, want to just send the ID for from_user and to_user but on response want to actually get the User objects back, if I add `depth` to the serializer then POST starts failing saying that `from_user` and `to_user` are required, even though I'm still passing them in. I've also tried sending in an object for `from_user` and `to_user` just to see if that'd work but it still complains that they're required. I think this is because depth sets them to read-only but then not sure how you're supposed to be able to set foreign keys at all when using depth, doesn't it defeat the point?

Is there a way to do this without defining your own create method on the viewset and switching serializers manually between the input (request) and output (response)? That's the only other solution I've come up with.

    def create(self, request, *args, **kwargs):
        serializer
= FriendshipRequestSerializer(data=request.data)
       
if serializer.is_valid():
            instance
= serializer.save()
            headers
= self.get_success_headers(serializer.data)
            serializer
= FriendshipRequestReadSerializer(instance)
           
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

       
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Xavier Ordoquy

unread,
Nov 21, 2015, 2:46:22 AM11/21/15
to Django REST framework
You likely want to set all the nested serializer field as read only except for the id. The way, you'll be able to change / update the related objects through the ID and still get all the fields.

Regards,
Xavier,
Linovia.
 

Joshua Turmel

unread,
Nov 21, 2015, 3:53:39 PM11/21/15
to Django REST framework
I'm not actually trying to update the nested object, just create the object that has the foreign keys on it but then when it returns the result, return the nested object rather than the IDs I just POSTed.

JT

Andrew Backer

unread,
Nov 23, 2015, 6:55:39 AM11/23/15
to Django REST framework
I am curious about this too.  We wrote a custom helper that switched between two different fields based on "get" vs "post/patch", but it's kinda ugly to configure.  There is a custom mixin, and then you need to define an `on_read` and `on_write` dictionary of field mappings.  Honestly, a derived serializer and using `get_serializer` would probably be easier.

Kaviraj Kanagaraj

unread,
Nov 25, 2015, 1:22:36 AM11/25/15
to Django REST framework
I have faced similar kind of problems. Consider solving by creating Model serializer for FriendshipRequest the following way

class  FriendshipRequestSerializer(serializers.ModelSerializer):
   from_user_id
=  serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), write_only=True)
   from_user  
=  UserSerializer(read_only=True)
   to_user_id
= serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), write_only=True)
   to_user
= UserSerializer(read_only=True)



Now while POSTing just send from_user_id and to_user_id, you will get the user details as response.
NOTE: You should write UserSerializer accordingly. Hope this helps.
Reply all
Reply to author
Forward
0 new messages