Create a Book instance with multiple tags in Django REST Framework

I am new to Django and I have created 2 models named ‘Book’ and ‘Tag’ and I tried this way-

Model Class

class Tag(models.Model):

    name = models.CharField(max_length=50, unique=True)


    def __str__(self):
        return self.name + '___'

class Book(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=100)
    tags = models.ManyToManyField(Tag)

    def __str__(self):
        return self.title

Searializer Class

class TagSerializer(serializers.ModelSerializer):

    class Meta:
        model = Tag
        fields = ['id', 'name']

class BookSerializer(serializers.ModelSerializer):
    tags = serializers.ListField(child=serializers.CharField())

    class Meta:
        model = Book
        fields = ['id', 'title', 'tags']

    def save(self, **kwargs):
        tags = self.validated_data.pop('tags', [])
        book = BookModel.objects.create(**self.validated_data)

        if len(tags):
            tag_objs = []
            for tag_name in tags:
                tag_obj, created = Tag.objects.get_or_create(name=tag_name)
                tag_objs.append(tag_obj)
                book.tags.add(tag_obj) # Having an error in this line

View Class

class BookList(APIView):
    """List all Book and create new one in Book app"""

    def get(self, request, format=None):
        book = Book.objects.all()
        serializer = BookSerializer(book, many=True)

        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request, format=None):
        data = request.data

        serializer = BookSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Here, My request body will be-

{
    title: 'Essential English Grammar',
    tags: ['lesson', 'english']
}

And I need the following response with get request-

{
    id: UUID
    title: 'Essential English Grammar',
    tags: ['lesson', 'english']
}

I need reverse relationship means I will be able to fetch all Books with a Tag. Please help me to solve this problem

ManyToMany relationships work the same and equally well in both directions.

Review the docs and examples at Many-to-many relationships | Django documentation | Django

Thanks sir, I have used Many-to-many relationship. But a problem I am facing in the Serializer’s save method. I mentioned with # comment. Could you please solve this issue?

What is the specific error you are receiving? Please post the traceback.

Error:
“Got KeyError when attempting to get a value for field tags on serializer BookSerializer.\nThe serializer field might be named incorrectly and not match any attribute or key on the OrderedDict instance.\nOriginal exception text was: ‘tags’.”

Serializer class

book.tags.add(tag_obj) # Having an error in this line

Here I guess, tag_obj is being added to the book instance (id: uuid, tag: something) but I want my response model like,

{ ....
    tags: ['lesson']
}

not

tags: {
            id: uuid,
            name: 'lesson'
          }

Thanks for your kind response sir.

Please post the complete traceback from the error message you’re receiving.

Before they can be related in a many-to-many relationship, both records must exist in the database. That is why the error is coming.


These types of errors will come. Check once both values are saved in the database before making the relationship. Let me know if it’s fixed or not…
Check the documentation here