Search code examples
pythondjangomany-to-manydjango-queryset

I don't know how to through one queryset type to manytomany relations


I want to use Django to write a blog system.But the question is I can't get tags queryset from articles queryset.

models:

class Article(models.Model):
    ...
    tags = models.ManyToManyField(Tags,related_name='tags')
    author = models.ForeignKey(
        User,on_delete=models.CASCADE,to_field="username",
    )
    ...

class Tags(models.Model):
    tag_name = models.CharField(max_length=20)
    def __str__(self):
        return self.tag_name
class Profile(models.Model):
    user = models.OneToOneField(User,on_delete=models.CASCADE,to_field='username',)
    ...

views:

....
def get_context_data(self,**kwargs):
    user=self.request.user
    object_list=Article.objects.all().filter(author=self.request.user.username).order_by(F('created').desc())[:100]
    kwargs['tags']=??? # I want to get a tags queryset related to object_list
    return super(UserIndexView,self).get_context_data(**kwargs)

Solution

  • You are using related_name wrong. related_name is the name for the reversed relationship. It should be:

    tags = models.ManyToManyField(Tags,related_name='articles')
    

    So the simple answer to your question is use:

    [article.tags.all() for article in object_list]
    

    But this is not efficient since it issues 100 separate queries to the DB. A better way to do this would be:

    Tags.objects.filter(articles__author=self.request.user.username)
    

    (Note the use of the related_name property)

    But I've omitted the interesting part of only getting tags related to the 100 newest articles of the user. To do this, I think the best way is to first get the date of the 100th article, and then filter accordingly:

    ordered_articles = Article.objects.filter(author=self.request.user.username).order_by(F('created').desc()
    try:
        date_limit = ordered_articles[100].created
        return Tags.objects.filter(articles__author=self.request.user.username, articles__created__lt=date_limit)
    except IndexError:
        return Tags.objects.filter(articles__author=self.request.user.username)
    

    (Answer not tested, sorry)

    Also, call your model Tag instead of Tags.