Django rest framework serializing many to many field
Solution 1
You will need a TagSerializer
, whose class Meta
has model = Tag
. After TagSerializer
is created, modify the PostSerializer
with many=True
for a ManyToManyField
relation:
class PostSerializer(serializers.ModelSerializer):
tag = TagSerializer(read_only=True, many=True)
class Meta:
model = Post
fields = ('tag', 'text',)
Solution 2
This is what I did, let´s suppose a Book can have more than one author and an Author can have more than one book: On Model:
class Author(models.Model):
name = models.CharField(max_length=100, default="")
last_name = models.IntegerField(default=0)
class Book(models.Model):
authors = models.ManyToManyField(Author, related_name="book_list", blank=True)
name = models.CharField(max_length=100, default="")
published = models.BooleanField(default=True)
On Serializers:
class BookSerializer(serializers.ModelSerializer):
authors = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), many=True)
class Meta:
model = Book
fields = ('id', 'name', 'published', 'authors')
class AuthorSerializer(serializers.ModelSerializer):
book_list = BookSerializer(many=True, read_only=True)
class Meta:
model = Author
fields = ('id', 'name', 'last_name', 'book_list')
Solution 3
Adding to @Brian's answer "tags": [{"name": "tag1"}] can be simplified to "tags": ["tag1", "tag2",...] in this way:
class TagListingField(serializers.RelatedField):
def to_representation(self, value):
return value.name
class PostSerializer(serializers.ModelSerializer):
tag = TagListingField(many=True, read_only=True)
class Meta:
...
More info here: https://www.django-rest-framework.org/api-guide/relations/#custom-relational-fields
Solution 4
The default ModelSerializer
uses primary keys for relationships. However, you can easily generate nested representations using the Meta
depth
attribute:
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ("text", "tag")
depth = 1
As mentioned in the documentation :
The
depth
option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.
Solution 5
This works for me.
tag = TagSerializer(source="tag", read_only=True, many=True)
Related videos on Youtube
kengcc
Updated on February 19, 2022Comments
-
kengcc about 2 years
How do I serialize a many-to-many field into list of something, and return them through rest framework? In my example below, I try to return the post together with a list of tags associated with it.
models.py
class post(models.Model): tag = models.ManyToManyField(Tag) text = models.CharField(max_length=100)
serializers.py
class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ("text", "tag"??)
views.py
class PostViewSet(viewsets.ReadOnlyModelViewSet): queryset = Post.objects.all() serializer_class = PostSerializer
-
kengcc over 8 yearsUsing help from @Brian I manage to list the items in this form: "tags": [{"name": "tag1"}]. I would like to simplify it to list, is it possible: "tags": ["tag1", "tag2",...]
-
M. Dhaouadi over 6 yearsuse ` tags = serializers.SlugRelatedField(many=True,read_only=True, slug_field='title', //tag's fireld you want to show allow_null=True)` in PostSerializers
-
-
kengcc over 8 yearsit works!!! :D Any idea how to turn this serializer into just a comma separated list? class TagSerializer(serializers.ModelSerializer): class Meta: model = Tag fields = ('name')
-
kengcc over 8 yearsRight now, I get: "tags": [{"name": "tag1"}] I would like to simplify it to: "tags": ["tag1", "tag2",...]
-
Sachin Gupta over 8 yearstags = serializers.ListField(source='tag'). This will get you the list of the str representation of each object of tag
-
getup8 over 7 yearsWhat if you want to be able to update the tag through the Post? (e.g. not read_only) I'm getting weird behavior when I take away the read_only and try to PATCH an update to the tag field (I get an error about the tag already existing)
-
Pavel Vergeev almost 7 yearsThe
read_only=True
part is explained here: django-rest-framework.org/api-guide/relations/… -
Vladimir Prudnikov almost 6 yearsTry
tags=serializers.CharSerializer(source='tag__name', many=True)
, note double underscore. -
Kishan Mehta about 5 yearsAny idea how can we create authors on create of Book entity??
-
Jesus Almaral - Hackaprende about 5 yearsYes, it has to be done on the Views class, please post another question if you want a more detailed answer
-
bdoubleu almost 5 yearsFor
get_topics_list
you could simplify toreturn list(instance.topics.values_list('desc', flat=True))
-
Олег Войтинський over 4 yearsYou also must include a source attribute in the tag for example
tag = TagSerializer(source="tag", read_only=True, many=True)
Where source is your many-to-many field in a Model. -
Piyush over 2 yearsAfter doing this how it will update
tag
array ???