ragmha
ragmha

Reputation: 631

Unable to send a PUT request on PrimaryKeyRelatedField

I am learning Django and trying to create a Game REST API using Django REST framework.I am not sure how to update the publisher field.Do I need to create another Serializer for my Publisher class and implement a save method?

I am using POSTMAN to send a PUT request and I am recieving this:

"publisher": [
    "Incorrect type. Expected pk value, received unicode."
  ]

when I send a JSON request

{
  "name": "Test",
  "release_date": "1979-01-01",
  "rating": 5,
  "comment": "Terrible Game!",
  "publisher": "Me"

}

models.py

class Publisher(models.Model):
    name = models.CharField(max_length=100)

    def __unicode__(self):
        return self.name

class Game(models.Model):
    name = models.CharField(max_length=100)
    release_date = models.DateField(null=True, blank=True)
    rating = models.IntegerField(
        null=True, blank=True,
        validators=[MinValueValidator(0), MaxValueValidator(5)])
    comment = models.TextField(null=True, blank=True)
    publisher = models.ForeignKey(Publisher, null=True, blank=True)

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ('name',)

serializers.py

from rest_framework import serializers
from game.models import Game, Publisher

class GameSerializer(serializers.ModelSerializer):
    publisher = serializers.PrimaryKeyRelatedField(allow_null=True, queryset=Publisher.objects.all(), required=False)

    class Meta:
        model = Game
        fields = ('pk','name', 'release_date', 'rating', 'comment', 'publisher')

    def create(self, validated_data):
        """
        Create and return a new 'Game' instance, given the validated data.
        """
        return Game.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing 'Game' instance, given the validated data.
        """
        instance.name = validated_data.get('name', instance.name)
        instance.release_date = validated_data.get('release_date',instance.release_date)
        instance.rating = validated_data.get('rating', instance.rating)
        instance.comment = validated_data.get('comment', instance.comment)
        instance.publisher = validated_data.get('publisher', instance.publisher)
        instance.save()
        return instance

views.py

class GameDetail(APIView):
    """
    Retrieve, update or delete a game instance.
    """
    def get_object(self,pk):
        try:
            return Game.objects.get(pk=pk)
        except Game.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        game = self.get_object(pk)
        serializer = GameSerializer(game)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        game = self.get_object(pk)
        serializer = GameSerializer(game, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        game = self.get_object(pk)
        game.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Upvotes: 1

Views: 761

Answers (1)

Nicolas W.
Nicolas W.

Reputation: 672

You're sending a string ("Me") as the publisher attribute. That's why you get your "Incorrect type. Expected pk value, received unicode." error.

Since publisher is a ForeignKey in your Game model, you'll have to get the instance of "Me" Publisher before saving it in your database.

One possible approach is to modify your update() method in your serializer and search for the right instance :

instance.publisher = Publisher.objects.get_or_create(name=validated_data.get('publisher'))
and then call instance.save().

Upvotes: 1

Related Questions