4
\$\begingroup\$

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
\$\endgroup\$

1 Answer 1

7
\$\begingroup\$

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).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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