Annotate on related field

27 views
Skip to first unread message

Ramashish Baranwal

unread,
Jul 12, 2016, 7:28:30 AM7/12/16
to Django users
Hi,

I have the following model definitions:

class Tag(models.Model):
    name
= models.CharField(max_length=16)

class Blog(models.Model):
    name
= models.CharField(max_length=16)
    tags
= models.ManyToManyField(Tag, blank=True)



I want to select blogs with more than one tags. Here is what I am doing (for two tags)-

# select blogs for python and java
blogs
= Blog.objects.filter(tags__name='python').filter(tags__name='java')



This INNER joins Tag with Blog twice, each time filtering on the given name. This works well. Now I want to retrieve the matching tags. If it were a single join, I would have done-

blogs = blogs.annotate(tag=F('tags__name'))

Doing this still works, but only retrieves the last tag. How do I retrieve the tag name for each join, giving them different names? Something like-

# Below should give tag1 = 'python', tag2 = 'java'
blogs
= blogs.annotate(tag1=?, tag2=?)

Thanks,
Ramashish

Todor Velichkov

unread,
Jul 22, 2016, 5:19:56 PM7/22/16
to Django users
By "retrieving the matching tags" you mean fetching `Tag` objects?

Well I guess what you can do is to use `prefetch_related` with custom `Prefetch` object.

blogs = Blog.objects.prefetch_related(
    models
.Prefetch('tags',
        queryset
=Tag.objects.filter(name__in=['python', 'java'])
        to_attr
='my_tags'
   
)
)

#usage
for blog in blogs:
   
print blog.my_tags
Reply all
Reply to author
Forward
0 new messages