Reputation: 193
In my FollowingPageView function, I'm trying to filter posts based on the logged in user's list of user's he/she is following.
You'll see the Profile model has a "following" field that captures the names of users the Profile owner is following. What I'm trying to do in my view is capture these names of the users in "following" then pass them to Post.objects.filter(created_by=user_list), but I will only get the last user in that list in this case. How can I iterate over the "user_list" Queryset and pass that to Post.objects.filter in order to return the posts from each user in that list? In this case, I should have two users in the Queryset [<User: winter>, <User: daisy>].
models.py
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
bio = models.TextField(null=True, blank=True)
website = models.CharField(max_length=225, null=True, blank=True)
follower = models.ManyToManyField(User, blank=True, related_name="followed_user") # user following this profile
following = models.ManyToManyField(User, blank=True, related_name="following_user") # profile user that follows this profile
def __str__(self):
return f"{self.user}'s' profile id is {self.id}"
def following_users(self):
for username in self.following:
return username
def get_absolute_url(self):
return reverse("network:profile-detail", args=[str(self.id)])
class Post(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
subject = models.CharField(max_length=50)
body = models.TextField(max_length=1000)
timestamp = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, blank=True, related_name="posts")
def __str__(self):
return f"{self.created_by} posted {self.body}"
views.py
# Following Users
def FollowingPageView(request, pk):
profile = get_object_or_404(Profile, id=pk)
user_list = []
for user in profile.following.all():
user_list.append(user)
posts = Post.objects.filter(created_by=user_list[0])
print(user_list)
paginator = Paginator(posts, 10)
page_number = request.GET.get("page")
page_obj = paginator.get_page(page_number)
try:
if request.method == "GET":
return render(request, "network/follow-posts.html", { "profile": profile, "page_obj": page_obj })
except ValueError:
return render(request, "network:index.html", {"error": ValueError})
Upvotes: 0
Views: 651
Reputation: 37319
One approach is to use an __in
query. Here, because you're not using user_list
for anything else, you'll probably get the best results from using an inner query:
posts = Post.objects.filter(created_by__in=profile.following.all())
But note the performance advice in the linked docs - test it on your actual setup and see.
Possibly with a distinct()
call required, I can't remember exactly what triggers the possibility of duplicate records with many-to-many fields.
There are other ways to express it using field references, something like:
posts = Post.objects.filter(created_by__profile__followed_user=profile.user).distinct()
Backing databases tend to do that with a join rather than a subquery, so it can have different performance characteristics.
Upvotes: 1