Add Serializer on Reverse Relationship - Django Rest Framework
Solution 1
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',
)
Solution 2
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',)
Related videos on Youtube
Marcus Lind
Originally from Sweden, I lived in Bangkok, Thailand for 8 years and I'm currently living in London, United Kingdom where I work as a Lead AI Software Engineer and lead machine learning and data science teams working on projects for Fortune 500 companies. I have an entrepreneurial background, I founded Tourn -- a marketing platform for social media influencers -- which was acquired in 2014, and since then I've been involved in multiple e-commerce and mobile gaming startups. I am currently working with AI and Analytics cases with BCG GAMMA (Boston Consulting Group) in London. My background has given me experience working with technologies such as Django, Python, Angular, Javascript, Spark, Hadoop, Docker, Ansible and more.
Updated on September 16, 2022Comments
-
Marcus Lind over 1 year
I have a
Cart
model and aCartItem
model. TheCartItem
model has aForeignKey
to theCart
model.Using Django Rest Framework I have a view where the API user can display the
Cart
, and obviously then I want to include theCartItem
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 theCartItem
model. If I exclude product from theCartItemSerializer
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.-
Ahmed Hosny about 8 yearstry
cartitem_set = CartItemSerializer(read_only=True, many=True)
-
-
Ranvijay Sachan almost 8 yearscan we change name cartitem_set to items ?
-
Aaron C. de Bruyn almost 7 yearsYou can change the name by doing something like: items = CartItemSerializer(read_only=True, many=True, source='cartitem_set')
-
Gonzalo over 6 yearsYou can change cartitem_set name, from related_name. In class CartItem : cart = models.ForeignKey(Cart, related_name='items') , then in "fields" inside serializer, you must use name items
-
Shahabaz about 5 yearsI have an issue here. I am not getting any column as cartitem_set in the JSON response any idea? (Data is present). Response returns without cartitem_set key pair .
-
Helen about 5 yearsIs it possible to use this solution then filter the items returned in the set?
-
Marcus Lind about 5 years@Helen you can pass in a source kwarg to the field and set a custom source if you want.
-
Helen about 5 yearsWhat would the syntax of that look like? I've currently got source set to source='cartitem_set' to change the name, but since it's a string, how would I pass a filter or a queryset into it? Appreciate your help Marcus.
-
adrian oviedo almost 4 yearsIn the original question he keeps the implicit related name: cartitem_set
-
Joel G Mathew over 2 yearsYes, this is very important for reverse relationship to work
-
Thorvald about 2 yearsThis solution is incredibly slow for bigger queries, any way to increase the performance here?
-
Thorvald about 2 yearsHad to use a prefetch_related on the query of course: prefetch_related('cartitem_set')