Here is my model:
from django.db import models
from django.db.models.expressions import F
class Publication(models.Model):
name = models.CharField('name of publication', max_length=1024, null=True, blank=True)
def __str__(self):
return f'{self.name}'
class Meta:
verbose_name = "Publication"
verbose_name_plural = "Publications"
class Book(models.Model):
name = models.CharField('name of book', max_length=1024, null=True, blank=True)
publication = models.ForeignKey(Publication, on_delete=models.CASCADE, related_name='books_publications', null=True, blank=True)
def __str__(self):
return f'{self.name}//{self.publication.name}'
class Meta:
verbose_name = "Book"
verbose_name_plural = "Book"
I want outcome json as single publication with list of book (Please show me using Django ORM query and Django Serializer OR using DRF):
Want Output JSON like below:
[
{
"id": 1,
"name": "publication 001",
"book": [
{
"id": 1,
"name": "Book 001"
},
{
"id": 2,
"name": "Book 002"
}
]
},
{
"id": 2,
"name": "publication 002",
"book": [
{
"id": 3,
"name": "Book 003"
},
{
"id": 4,
"name": "Book 004"
}
]
}
]
I tried it through several way but unable to solve it using django orm query. I've done it through raw query. But I wantto implement it through Django ORM Query. SO please help me. TIA
The following should do the trick using simple serializers
class BookSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializer.CharField()
class PublicationSerializer(serializers.Serializer):
id = serializers.IntegerField()
name = serializers.CharField()
book = BookSerializer(source="books_publications.all", many=True)
qs = Publication.objects.all()
data = PublicationSerializer(qs, many=True).data
source="book_set"
allows for an object field to be mapped to a different serializer field.
book_set
is the default related_name provided by Django. This means that
my_publication.book_set.all()
is equivalent to Book.objects.filter(publication=my_publication)
.
You should consider defining your own related_name
.
publication = models.ForeignKey(Publication, on_delete=models.CASCADE, null=True, blank=True, related_name="books")
Note that the above code will result in N+1 queries to the database. A first one to get all publications and one for each publication to get related books.
You can and should use prefetch_related to reduce the number of query to two.
qs = Publication.objects.all()
qs = qs.prefetch_related("books_publications")
data = PublicationSerializer(qs, many=True).data
Alternatively you could use ModelSerializer
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ("id", "name")
class PublicationSerializer(serializers.ModelSerializer):
book = BookSerializer(source="books_publications.all", many=True)
class Meta:
model = Publication
fields = ("id", "name", "book")