Ezekiel Adetoro
Ezekiel Adetoro

Reputation: 11

Django ORM for loop to get queryset

I am trying to use for loop to get list of author with the number of books writing and author with the title of book wrote. Here is my models.py

class Author(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name


class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

    def __str__(self):
        return self.title

I have tried to loop through like this:

for a in Author.all():
    books = a.book_set.order_by('author')
    print(books)

I get the authors as they are in DB. Also,

for book in book_set.iterator():
...     print(book.title)

I got the list of all books.

I use author_list = Author.objects.order_by("book").count() which gave the number of author. How can I loop through the DB and get the Author with number of books, and Authors with book title wrote.

Upvotes: 1

Views: 661

Answers (1)

Risadinha
Risadinha

Reputation: 16666

Presuming that you want to list all others with their first 5 books (sorted alphabetically) and their total count of books on one page with a single fetch, you will need to use aggregations/annotations.

Author.objects.annotate(
    book_count=Count('book'),
    book_list=ArrayAgg('book__title', ordering='book__title')
).order_by('name').all()

In your template:

{% for author in author_list %}
    {author.name} ({author.book_count}):
    <ul>
    {% for book_title in author.book_list %}
        <li>{book_title}</li>
    {% endfor %}
    </ul>
{% endfor %}

This is just a SAMPLE and UNTESTED. It is just to get you started. Please consult the documentation. It makes use of the postgres specific ArrayAgg.

Upvotes: 1

Related Questions