Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add Serializer on Reverse Relationship - Django Rest Framework

Tags:

I have a Cart model and a CartItem model. The CartItem model has a ForeignKey to the Cart model.

Using Django Rest Framework I have a view where the API user can display the Cart, and obviously then I want to include the CartItem in the respone.

I set up my Serializer like this:

class CartSerializer(serializers.ModelSerializer):     user = UserSerializer(read_only=True)     cartitem_set = CartItemSerializer(read_only=True)     class Meta:         model = Cart         depth = 1         fields = (             'id',              'user',              'date_created',              'voucher',              'carrier',              'currency',              'cartitem_set',          ) 

My problem is the second line, cartitem_set = CartItemSerializer(read_only=True).

I get AttributeErrors saying 'RelatedManager' object has no attribute 'product'. ('product' is a field in the CartItem model. If I exclude product from the CartItemSerializer I just get a new AttributeError with the next field and so on. No matter if I only leave 1 or all fields in the Serializer, I will get a error.

My guess is that for some reason Django REST Framework does not support adding Serializers to reverse relationships like this. Am I wrong? How should I do this?

PS

The reason why I want to use the CartItemSerializer() is because I want to have control of what is displayed in the response.

like image 934
Marcus Lind Avatar asked Feb 09 '16 06:02

Marcus Lind


2 Answers

Ahmed Hosny was correct in his answer. It required the many parameter to be set to True to work.

So final version of the CartSerializer looked like this:

class CartSerializer(serializers.ModelSerializer):     cartitem_set = CartItemSerializer(read_only=True, many=True) # many=True is required     class Meta:         model = Cart         depth = 1         fields = (             'id',              'date_created',              'voucher',              'carrier',              'currency',              'cartitem_set',          ) 
like image 56
Marcus Lind Avatar answered Sep 19 '22 13:09

Marcus Lind


It's important to define a related name in your models, and to use that related name in the serializer relationship:

class Cart(models.Model):    name = models.CharField(max_length=500)  class CartItem(models.Model):    cart = models.ForeignKey(Cart, related_name='cart_items')    items = models.IntegerField() 

Then in your serializer definition you use those exact names:

class CartSerializer(serializers.ModelSerializer):     cart_items = CartItemSerializer(read_only=True)     class Meta:        model = Cart        fields = ('name', 'cart_items',) 
like image 22
djq Avatar answered Sep 17 '22 13:09

djq