2

I have two models

class Account(AbstractBaseUser, PermissionsMixin):
    followers = models.ManyToManyField(
        'Account', related_name='followers',
        blank=True,
    )
    following = models.ManyToManyField(
        'Account', related_name='following',
        blank=True,
    )

and

class Article(models.Model):
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
    )

I'm writing an application where users subscribe to each other and create articles.

How can I make a request to receive all the articles from those to whom I am subscribed? I'm trying to do something like: (pseudo-code)

user = self.get_object()
articles = Article.objects.filter(author=user.followers.all())

But I know that this is not right

Alasdair
  • 298,606
  • 55
  • 578
  • 516
woe-dev.
  • 933
  • 1
  • 7
  • 12
  • If a user is `following` you, then that user is one of your `followers`, hence by introducing two relations, you introduce *data duplication* which is typically a bad idea. – Willem Van Onsem May 23 '18 at 10:12

3 Answers3

4

You can get list of following first, and then filter articles based on this list using __in:

user = self.get_object()
following = user.following.values_list('id', flat=True)
articles = Article.objects.filter(author_id__in=following)
neverwalkaloner
  • 46,181
  • 7
  • 92
  • 100
3

You don't need two many-to-many fields.

For example, you can remove the followers many-to-many field, then get the followers for an account by using the reverse relationship of the following field.

class Account(AbstractBaseUser, PermissionsMixin):
    following = models.ManyToManyField(
        'Account', 
        related_name='followers',
        blank=True,
    )

Then you can use the double underscore notation to filter on the many-to-many field:

articles = Article.objects.filter(author__followers=user)
Alasdair
  • 298,606
  • 55
  • 578
  • 516
0

You might want to split up followers and following fields into two classes. (PseudoCode)

class Following():
    author_id = models.foreignkey('Author')
    following_authors = models.integerfield('Following_Authors')

Loop into all authors you are following and append to a list. Of course, your Articles should have an article field that have their articles posted.

AuthorOfArticle = Author.objects.get(author='author to get all following')

FollowingAuthorsObj = Following.objects.filter(author=AuthorOfArticle.author) #get all the authors you are following.

ArticlesOfAuthor=[] #create a list variable
for authors in FollowingAuthorsObj: #loop through all you are following
    ArticlesOfAuthor.append(Article.objects.filter(author=authors[0].author)) 
#save it to a list of all articles.

Hope this helps.