Search code examples
pythondjangodjango-rest-frameworkdjango-rest-viewsets

ValueError: Cannot assign "u'http://localhost:8000/players/1/'": "Game.referee" must be a "User" instance


I understand what this error is saying, just not understanding how to pass user instance in a request(postman).

Following is my model.

class Game(models.Model):
    referee = models.ForeignKey(User, on_delete=models.CASCADE, related_name='referee')
    player_1 = models.ForeignKey(User, on_delete=models.CASCADE, related_name='opponent_1')
    player_2 = models.ForeignKey(User, on_delete=models.CASCADE, related_name='opponent_2')
    attacker = models.ForeignKey(User, on_delete=models.CASCADE, related_name='attacker')
    status = models.CharField(max_length=20, choices=GAME_STATUS, default='QUEUED')
    game_type = models.CharField(max_length=20, choices=GAME_TYPE, default='LEAGUE')

serializer.

class GameSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = Game
        fields = ('__all__')

and viewset is

class GameViewSet(viewsets.ModelViewSet):
    queryset = Game.objects.all()
    serializer_class = GameSerializer

Till here "u'http://localhost:8000/players/1/'" works fine.
As soon as I do following .

def create(self, request):
    game = Game.objects.create(
        referee = request.data.get('referee', request.user),
        player_1 = request.data.get('player_1', None),
        player_2 = request.data.get('player_2', None),
        attacker = request.data.get('attacker', None),
        status = request.data.get('status', None),
        game_type = request.data.get('game_type', None)
        )
    game.save()
    return game 

the same API call throws following error
ValueError: Cannot assign "u'http://localhost:8000/players/1/'": "Game.referee" must be a "User" instance.

Should I really create user instance from the url or there is more elegant way to pass the user instance?


Solution

  • So after inspecting the CreateModelMixin, I got an idea and I did the following.

    def create(self, request):
        serializer = self.get_serializer(data=request.data)
    
        # just to be cautious 
        serializer.is_valid(raise_exception=True)
    
        # actually converts urls to instances
        data = serializer.validated_data
    
        print data 
        # OrderedDict([(u'status', u'QUEUED'), (u'game_type', u'LEAGUE'), (u'referee', <User: kishor>), (u'player_1', <User: joey>), (u'player_2', <User: nick>), (u'attacker', <User: joey>)])
    
        # I can access model fields like below.
        print data["referee"].username