Reputation: 513
I'm currently building a website with the Django Framework. I want on the homepage of my website to display all posts made by people the user is following. Here are the classes for Profile, Story and Follow:
class Profile(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=30, null=True)
class Follow(models.Model):
following = models.ForeignKey('Profile', on_delete=models.CASCADE, related_name="following")
follower = models.ForeignKey('Profile', on_delete=models.CASCADE, related_name="follower")
follow_time = models.DateTimeField(auto_now=True)
class Story(models.Model):
author = models.ForeignKey('accounts.Profile', on_delete=models.CASCADE, related_name="author")
title = models.CharField(max_length=50)
content = models.TextField(max_length=10000)
As you can see Follow uses two Foreign Keys to represent the following and the follower. Is there a way to query all stories from people the user is following?
I really don't know what to filter. Or is this maybe a job for aggregation? If someone could help me, that would be awesome!
following_feed = Story.object.filter(???).order_by('-creation_date')
Upvotes: 4
Views: 2241
Reputation: 476709
One can use double underscores (__
) to look "through" relations (like ForeignKey
s, etc.).
So here we can filter like:
Story.objects.filter(
author__following__follower=my_profile
)
So by using author
we obtain a reference to the Profile
of the author, then with following
we look at the Follow
model and then finally with follower
we again obtain a reference to Profile
(s): the profile(s) of the follower(s).
my_profile
of course need to be substituted with a Profile
object (the profile of the person that is a follower
of the author
s of the Story
s you wish to obtain).
This will generate a query like:
SELECT s.*
FROM story AS s
JOIN follow AS f ON f.following_id = s.author_id
WHERE f.follower_id = 123
where 123
is the id
of the my_profile
.
If a person is following another person multiple times (here this can happen since you do not enforce that the follower, following
tuples are unique in the Follow
model), then the corresponding Story
s will be yielded multiple times.
It is therefore probably better to add a unique_together
constraint in the Follow
model:
class Follow(models.Model):
following = models.ForeignKey(
'Profile',
on_delete=models.CASCADE,
related_name="following"
)
follower = models.ForeignKey(
'Profile',
on_delete=models.CASCADE,
related_name="follower"
)
follow_time = models.DateTimeField(auto_now=True)
class Meta:
unique_together = (('following', 'follower'), )
It might also be worth to see the Follow
model as the through
model of a ManyToManyField
[Django-doc].
Upvotes: 7
Reputation: 3205
Note that I haven't tested the code I am posting so tell me if something is missing.
First, you need to get all the Profiles
that your users follow. Then you have to get the Stories
that they have.
followed_people = Follow.objects.filter(follower=current_user).values('following')
stories = Story.objects.filter(author__in=followed_people)
Upvotes: 2