I have a view that displays posts created by users that actual logged in user follows. It works, by I think the way I've done it isn't good.

BTW, UserProfile is my default user model.

UserFollower model

class UserFollower(models.Model):
    followed = models.OneToOneField(UserProfile, related_name="followed")
    followers = models.ManyToManyField(UserProfile, related_name="followers", blank=True)

Post model

class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL)
    body = models.CharField(max_length=140)

My page view

class MyPage(ListView):
    model = Post

    def get_queryset(self):
        posts = []
        for user in self.request.user.followers.all():
            for post in Post.objects.filter(author=user.followed):
                posts.append(post)

        return posts
up vote 7 down vote accepted

Let's focus on the selecting.

class MyPage(ListView):
    model = Post

    def get_queryset(self):
        posts = []
        for user in self.request.user.followers.all():
            for post in Post.objects.filter(author=user.followed):
                posts.append(post)

        return posts

This is a bit convoluted: you're performing a lot of queries (depending on how many followers a user has). Ideally you'd like to perform just one query.

Also, get_queryset looks like it will return a queryset, instead of a list.

class MyPage(ListView):
    model = Post

    def get_queryset(self):
        return Post.objects.filter(author__followers__follower__id=self.request.user.id)

Should work just as well, and returns an actual queryset. (I'm not sure if I got the exact syntax right, please look at https://docs.djangoproject.com/es/1.9/topics/db/queries/#spanning-multi-valued-relationships if it does not work).

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.