Reputation:
When I call serializer.data
, ManyToManyField will be displayed as list of ids,
but I want it to show tags
's names instead of ids.
models.py
class Tag(models.Model):
name = models.CharField(unique=True, max_length=20)
class Story(models.Model):
title = models.CharField(max_length=100)
tags = models.ManyToManyField(Tag)
serializers.py
from rest_framework import serializers
from stories.models import Story, Tag
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = ('name',)
class StorySerializer(serializers.ModelSerializer):
class Meta:
model = Story
fields = ('title', 'tags')
def is_valid(self, raise_exception=False):
self.initial_data['tags'] = self.get_tags_ids(self.initial_data['tags'])
return super().is_valid(raise_exception)
def get_tags_ids(self, tags):
tags_ids = []
for tag in tags:
tag, _ = Tag.objects.get_or_create(name=tag)
tags_ids.append(tag.id)
return tags_ids
then in shell
In [1]: from stories.serializers import StorySerializer
In [2]: StorySerializer()
Out[2]:
StorySerializer():
title = CharField(max_length=100)
tags = PrimaryKeyRelatedField(allow_empty=False, many=True, queryset=Tag.objects.all())
In [3]: TEST_DATA = {
...: 'title': 'A story',
...: 'tags': ['horror', 'action'],
...: }
In [4]: ser = StorySerializer(data=TEST_DATA)
In [5]: ser.is_valid()
Out[5]: True
In [6]: ser.data
Out[6]: {'title': 'A story', 'tags': [1, 2]}
How to let ser.data
return {'title': 'A story', 'tags': ['horror', 'action']}
instead?
Upvotes: 0
Views: 1504
Reputation: 2132
You can use StringRelatedField
link
In your model add this method
class Tag(models.Model):
name = models.CharField(unique=True, max_length=20)
def __str__(self) : # <- This Method in Tag Model
return self.name
Serializer.py
class StorySerializer(serializers.ModelSerializer):
tags = serializers.StringRelatedField(many=True) # <- This line
class Meta:
model = Story
fields = ('title', 'tags')
There is another way also to do it - Nested Serializer
Serializer.py
class TagsSerializer(serializers.ModelSerializer): # <- This Serializer
class Meta:
model = Tags
fields = ('name',)
class StorySerializer(serializers.ModelSerializer):
tags = TagsSerializer(many=True, read_only=True) # <- This line
class Meta:
model = Story
fields = ('title', 'tags')
Upvotes: 0