MistyD
MistyD

Reputation: 17223

Updating through put getting exception : Incorrect type. Expected pk value, received dict

I have the following two models

class modelJob(models.Model):
    category            = models.ForeignKey(modelJobCategory,on_delete=models.CASCADE,null=True,default=None,blank=True)
    description         = models.CharField(max_length=200, unique=False)

and this model

class modelJobCategory(models.Model):
    name = models.CharField(max_length=200, unique=True)
    other = models.CharField(max_length=200, unique=False , blank=True , null=True)

These are my two serializers

class Serializer_Update_Job_Serializer(ModelSerializer):
    class Meta:
        model = modelJob
        category = Serializer_Create_List_JobCategory
        fields = [
            'category',
            'description',
        ]

class Serializer_Create_List_JobCategory(ModelSerializer):
    class Meta:
        model = modelJobCategory
        fields = [
            'name',
            'other',
        ]

Now I am attempting to update through PUT at the url with a lookup field pk however I am getting the exception

{
  "category": [
    "Incorrect type. Expected pk value, received dict."
  ]
}

This is what my view looks like

class UpdateJob_RetrieveUpdateAPIView(RetrieveUpdateAPIView):
    queryset = modelJob.objects.all()
    serializer_class = Serializer_Update_Job_Serializer
    lookup_field = 'id'

    def put(self, request, *args, **kwargs):
        object = self.queryset
        return self.update(request, *args, **kwargs)

Any idea why I am getting this error ?

This is the body of my PUT

{
    "description": "foobar",

    "category" : {
        "name" : "labor",
        "other" : "blah"
    }

}

Upvotes: 3

Views: 1763

Answers (1)

aychedee
aychedee

Reputation: 25599

I believe you need to create an 'update' method on your job serializer. See the documentation here: http://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers. By default a serializer doesn't understand how to save a nested serializer.

Your update method might look like this:

def update(self, instance, validated_data, id):
    # Perform any updates to the instance you want to do
    # using the validated_data, then save the category
    instance.category = modelJobCategory.objects.get_or_create(
        name=validated_data['category']['name']
    )

A simpler, perhaps nicer approach would be to use a writable SlugRelatedField. So changing your update job serializer to have a category field that looks like:

category = SlugRelatedField(slug_field='name')

This way when you are saving the job with it's category you just send the name of the category. Not the whole category object.

If you want to understand what the error means. Django rest framework is trying to figure out which category to save on your job. But to do that it would use a primary key. The database id. An integer. What you're sending in your PUT request is the category dict, with name and description. But no database id. And django has no idea how to turn that dictionary object into a category that it can save to the database for you.

Upvotes: 3

Related Questions