I'm creating an API for a website for which I have a table with Books, another with Hashtags (which basically is a catalog of hashtags, e.g. "#traveling" ) and an intermediate table to establish many-to-many relationships between Books and Hashtags. My models are:
# models.py
class Books(models.Model):
id_books = models.AutoField(primary_key=True)
title = models.CharField(max_length=150)
class Hashtags(models.Model):
id_hashtags = models.AutoField(primary_key=True)
hashtag = models.CharField(max_length=150)
class Books_Hashtags(models.Model):
id_books_hashtags = models.AutoField(primary_key=True)
id_books = models.ForeignKey(Books, on_delete=models.CASCADE)
id_hashtags = models.ForeignKey(Hashtags, on_delete=models.CASCADE)
class Meta:
unique_together = ("id_books", "id_hashtags")
I'd like to have an API that provides an output like this:
[
{
"id_books": 1,
"title": "The Hobbit",
"hashtags": [
{
"id_hashtags": 1,
"hashtag": "fantasy"
},
{
"id_hashtags": 2,
"hashtag": "fiction"
},
{
"id_hashtags": 3,
"hashtag": "middle earth"
},
]
}
]
For this purpose I've serialized the models above using DRF following some examples that I've found online:
#serializers.py
from rest_framework import serializers
from app.models import Books, Books_Hashtags, Hashtags
class HashtagsSerializer(serializers.ModelSerializer):
hashtags = serializers.CharField()
class Meta:
model = Hashtags
fields = ('hashtag',)
class Books_HashtagsSerializer(serializers.ModelSerializer):
id_hashtag = HashtagsSerializer(many=True, read_only=True)
class Meta:
model = Books_Hashtags
fields = ('id_hashtags',)
class BooksSerializer(serializers.ModelSerializer):
id_books = serializers.IntegerField()
id_books_hashtags = Books_HashtagsSerializer(many=True, read_only=True)
title = serializers.CharField()
class Meta:
model = Books
fields = ('id_books', 'title', 'id_books_hashtags',)
My views look like this:
#views.py
from ntgBackend.models import Books
from rest_framework import viewsets
from api.serializers import BooksSerializer
class BooksViewSet(viewsets.ModelViewSet):
serializer_class = BooksSerializer
queryset = Books.objects.all()
So far, I've managed to obtain the following output from the API:
[
{
"id_books": 1,
"title": "The Hobbit",
}
]
But no information regarding hashtags, which I know they exist in the DB. I'm using DRF 3.8.2 with a MySQL DB and Django 2.0.2. Please help!
I was having the same problem and got to the following with some research:
In models.py only modify your Book model to include a ManyToManyField with Hashtags using Books_Hashtagas as your middle table. Also be sure to declare your Hashtag model before the Book one for the reference to work
# models.py
class Books(models.Model):
id_books = models.AutoField(primary_key=True)
title = models.CharField(max_length=150)
hashtags = models.ManyToManyField(Hashtags, related_name='hashTg', through="Books_Hashtags"
In your serializers file be sure to add depth = 1 in order to get what you need, otherwise you'll only get the hashtag id (This is for a ListAPI only)
#serializers.py
class BooksSerializer(serializers.ModelSerializer):
class Meta:
model = Books
#In case you want to filter out some fields:
#fields = ('field_A','field_B' )
fields = '__all__'
depth = 1
In views I'm using generics since they solve most of my needs:
#views.py
from ntgBackend.models import Books
from rest_framework import generics
from api.serializers import BooksSerializer
class BooksViewSet(generics.ListCreateAPIView):
serializer_class = BooksSerializer
queryset = Books.objects.all()
I'm quite new to this, I hope it helps. I'm using almost the same versions as you except Django(2.0.4).
Good luck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With