Search code examples
djangoforeign-keysmany-to-manydjango-rest-frameworkkeyerror

KeyError on relation field in Django-REST


I have the following models:

class ProductColor(models.Model):
    color_title = models.CharField(max_length=50)

class BasicProduct(models.Model):

    product_title = models.CharField(max_length=150)
    product_desc = models.TextField()
    product_price = models.FloatField(default=10.0)

    # Describes what colors are available for this product
    product_colors = models.ManyToManyField(ProductColor)

class BasicCartItem(models.Model):
    cart_product = models.ForeignKey(BasicProduct)
    cart_color = models.ForeignKey(ProductColor, blank=True, default=None, null=True)

And my ModelSerializer:

class CartSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.BasicCartItem

I'm giving my view this input:

{'cart_product': 1}

Then running the code:

    m = CartSerializer(data=inputdata)
    if m.is_valid():
        items = m.data # Generates KeyError: u'cart_color'

Extract of stacktrace:

  File "python2.7/site-packages/rest_framework/serializers.py", line 430, in to_representation
    attribute = field.get_attribute(instance)
  File "python2.7/site-packages/rest_framework/relations.py", line 103, in get_attribute
    return get_attribute(instance, self.source_attrs)
  File "python2.7/site-packages/rest_framework/fields.py", line 69, in get_attribute


  instance = instance[attr]
KeyError: u'cart_color'

Anyone with good knowledge knows what's going on here? I've been stuck here for hours and I don't know what I'm doing wrong..

Thanks.


Solution

  • You are accessing the data in a wrong way. You should access .validated_data on the serializer instead of .data.

    m = CartSerializer(data=inputdata)
    if m.is_valid():
        items = m.validated_data # access validated data here
    

    Why serializer.data approach did not work for your case?

    When you are doing .data, the serializer will try to serialize the initial_data as you have not passed the instance argument. It will expect all the fields to be present but since cart_color is not present on the data, it will raise a KeyError.

    When should you generally use serializer.data then?

    You should generally use serializer.data when you are serializing an existing object. This would require you to pass an instance argument when creating an instance of the serializer.

    m = CartSerializer(instance=my_object)
    items = m.data # use .data when serializing an object