1

I have this models

class Book(models.Model):
    title = models.CharField(max_length=255, blank=False, null=False)

class Like(models.Model):
    user = models.ForeignKey(User, related_name="like_user", blank=False, null=False)
    book = models.ForeignKey(Book, related_name="like_book", blank=False, null=False)
    class Meta:
        unique_together = ["user", "book"]

I want get all books and check if current user liked each book in single request

Book.objects.select_related('like_book').all()

won't work because of many results

Book.objects.prefetch_related('like_book').all()

will cache like_set but it will contain all likes for this Book. Not only one for this user.

In the end i want to have additional field is_liked

books = Book.objects.MAGIC_FETCH('like_book', user=self.request.user).all()
books[0].is_liked
cyberlis
  • 61
  • 6
  • 1
    Have a look at this answer which is doing something very similar to what you want: http://stackoverflow.com/a/30650380/3955830 – solarissmoke Apr 20 '16 at 02:37
  • @solarissmoke it is very close to what I want. I think I could use it as answer to my question. But it is still interesting if it is any way to do this more elegant without external query. But thank you very much – cyberlis Apr 20 '16 at 06:52

1 Answers1

2

* Updated to address comments *

So roughly speaking, I think this is what you would use:

Book.objects.annotate(is_liked=Case(When(like__user=self.request.user, then=True), default=False))
2ps
  • 15,099
  • 2
  • 27
  • 47
  • 1
    The OP doesn't want to filter books which the current user has liked, but rather to fetch all books, but annotate the ones liked by the current user. – solarissmoke Apr 20 '16 at 02:42
  • @solarissmoke is right. I want ALL books and annotate the ones liked by the current user – cyberlis Apr 20 '16 at 06:48
  • @2ps it is so awesome! Thank You! – cyberlis Apr 20 '16 at 08:57
  • I've made it like this: `Book.objects.annotate(is_liked=Case( When(like_book__user=self.request.user, then=Value(True)), default=Value(False), output_field=BooleanField()))` – cyberlis Apr 20 '16 at 09:59