Pickels
Pickels

Reputation: 34680

Add a value to queryset

The title of my questions isn't really correct but I wasn't sure how to word it.

I have a queryset of books.

Book.objects.all()

I have a book relation:

class BookRelation(models.Model):
    user = models.ForeignKey(User, related_name='books')
    book = models.ForeignKey(Book, related_name='users')

    STATES = (
        (0, 'wishlist'),
        (1, 'reading'),
        (2, 'read'),
    )

I have a view that lists the book queryset but I would like to visually show that a user has a relationship to a book.

I was thinking of solving it by looping the queryset and then check if the user has a relationship to that book but I guess this is what they call n+1? So I was wondering if there is a better solution?

Upvotes: 0

Views: 1419

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599956

You can do this in two queries, plus a bit of processing. First, get all books; then, get all BookRelations for the user; then, iterate through to associate the books with the relations.

books = Book.objects.all()
user_relations = BookRelation.objects.filter(user=my_user)
# now create a dict of relations keyed by book id:
book_relations = dict((r.book_id, r) for r in user_relations)
# now annotate the books with relations if they exist:
for book in books:
    book.relation = book_relations.get(book.id)

Now each book in the queryset has a relation attribute which is the BookRelation for that user/book, if it exists.

Upvotes: 2

Related Questions