How to get value of ManyToMany field rather than their ids?
Question:
I have three models, as shown below:
class TagsModel(models.Model):
title = models.CharField(max_length=200)
def __str__(self):
return self.title
class ImagesModel(models.Model):
title = models.CharField(max_length=500, default='image')
image_cdn = models.TextField(null=True, blank=True)
image = models.ImageField(upload_to='articles/images/', null=True, blank=True)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class ArticlesModel(models.Model):
title = models.CharField(max_length=1000)
category = models.CharField(max_length=40, choices=category_choices, default=('General', 'General'))
summary = models.TextField(blank=False, null=True, max_length=5000)
tags = models.ManyToManyField(TagsModel, blank=True)
image = models.ImageField(blank=True, null=True, upload_to='articles/article-image/')
image_cdn = models.TextField(blank=True, null=True)
image_src = models.ForeignKey(ImagesModel, related_name='Image_cdn', on_delete=models.PROTECT, null=True)
images = models.ManyToManyField(ImagesModel, blank=True)
json = models.JSONField(null=True, blank=True)
html = models.TextField(blank=True, null=True)
is_published = models.BooleanField(default=False)
update = models.DateTimeField(auto_now_add=True)
timestamp = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('articles:article_detail', kwargs={'article_id': self.id})
And in the view.py
class ArticlesView(APIView):
def get(self, request):
articles_list = ArticlesModel.objects.all()
images_list = ImagesModel.objects.all()
images_serializer = ImagesSerializer(images_list, many=True)
articles_serializer = ArticlesListSerializer(articles_list, many=True)
return Response({
'images':images_serializer.data,
'articles':articles_serializer.data
})
So when I send request I get results like this:
The problem here is that I get the ids of Images and tags and not the objects themselves!
I am asking if there’s a way in django/DRF to get the objects (images, tags) included with the queries of Articles and not only their ids?
Answers:
Solution
class ProductSerializer(serializers.ModelSerializer):
cate = serializers.SerializerMethodField('get_cate')
def get_cate(self,obj):
return [cate.name for cate in obj.cate.all()]
class Meta:
model = ProductModel
fields = "__all__"
Response output
[
{
"id": 1,
"cate": [
"Category5",
"Category6"
],
"name": "Apple",
"price": "12.00",
"released_at": "2022-10-18T13:16:01Z"
},
{
"id": 2,
"cate": [
"Category1",
"Category2",
"Category3"
],
"name": "Kiwi",
"price": "20.00",
"released_at": "2022-10-18T13:16:01Z"
},
{
"id": 3,
"cate": [
"Category2",
"Category4",
"Category5",
"Category6"
],
"name": "Tomato",
"price": "25.00",
"released_at": "2022-10-18T13:16:01Z"
}
]
This is called serializer relations, You can find the solution to your issue & more suggestions in this article https://www.django-rest-framework.org/api-guide/relations/
I have three models, as shown below:
class TagsModel(models.Model):
title = models.CharField(max_length=200)
def __str__(self):
return self.title
class ImagesModel(models.Model):
title = models.CharField(max_length=500, default='image')
image_cdn = models.TextField(null=True, blank=True)
image = models.ImageField(upload_to='articles/images/', null=True, blank=True)
timestamp = models.DateTimeField(auto_now=True)
update = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class ArticlesModel(models.Model):
title = models.CharField(max_length=1000)
category = models.CharField(max_length=40, choices=category_choices, default=('General', 'General'))
summary = models.TextField(blank=False, null=True, max_length=5000)
tags = models.ManyToManyField(TagsModel, blank=True)
image = models.ImageField(blank=True, null=True, upload_to='articles/article-image/')
image_cdn = models.TextField(blank=True, null=True)
image_src = models.ForeignKey(ImagesModel, related_name='Image_cdn', on_delete=models.PROTECT, null=True)
images = models.ManyToManyField(ImagesModel, blank=True)
json = models.JSONField(null=True, blank=True)
html = models.TextField(blank=True, null=True)
is_published = models.BooleanField(default=False)
update = models.DateTimeField(auto_now_add=True)
timestamp = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('articles:article_detail', kwargs={'article_id': self.id})
And in the view.py
class ArticlesView(APIView):
def get(self, request):
articles_list = ArticlesModel.objects.all()
images_list = ImagesModel.objects.all()
images_serializer = ImagesSerializer(images_list, many=True)
articles_serializer = ArticlesListSerializer(articles_list, many=True)
return Response({
'images':images_serializer.data,
'articles':articles_serializer.data
})
So when I send request I get results like this:
The problem here is that I get the ids of Images and tags and not the objects themselves!
I am asking if there’s a way in django/DRF to get the objects (images, tags) included with the queries of Articles and not only their ids?
Solution
class ProductSerializer(serializers.ModelSerializer):
cate = serializers.SerializerMethodField('get_cate')
def get_cate(self,obj):
return [cate.name for cate in obj.cate.all()]
class Meta:
model = ProductModel
fields = "__all__"
Response output
[
{
"id": 1,
"cate": [
"Category5",
"Category6"
],
"name": "Apple",
"price": "12.00",
"released_at": "2022-10-18T13:16:01Z"
},
{
"id": 2,
"cate": [
"Category1",
"Category2",
"Category3"
],
"name": "Kiwi",
"price": "20.00",
"released_at": "2022-10-18T13:16:01Z"
},
{
"id": 3,
"cate": [
"Category2",
"Category4",
"Category5",
"Category6"
],
"name": "Tomato",
"price": "25.00",
"released_at": "2022-10-18T13:16:01Z"
}
]
This is called serializer relations, You can find the solution to your issue & more suggestions in this article https://www.django-rest-framework.org/api-guide/relations/