FilteredRelation() comes from Django 2.0. It helps to make the query faster than the filter in some cases. Suppose you have Blog posts. Now you want to filter out all the published posts who have author name, John.
relation_name is the field that you want to filter.
condition=Q() accept filtering object. Django prefer Q() to handle that operation.
FilteredRelation() is used
annotate() to handle filtering. Basically, it uses ON clause when JOIN is necessary.
class Post(models.Model): author = models.ForeignKey(Author) publication_status = models.IntegerField(default=0) # 0 = Draft, 1 = Publish, 2 = Archieve ... ...
from django.db.models import FilteredRelation, Q Post.objects.annotate( filtered_posts=FilteredRelation( 'author', condition=Q(status=1), ), ).filter(filtered_posts__name__iexact='John')
If there is a big amount of posts then above code will be faster than the below. Using,
FilteredRelation() on first code, it used only one WHERE clause when
Post.objects.filter( author__status=1, author__name__iexact='John' )
Note: It doesn’t support on nested relations. For example, author may have a foreign key with role. So, in this case, we can’t use author__role. Example below,
Post.objects.annotate( filtered_posts=FilteredRelation( 'author__role', condition=Q(status=1), ), ).filter(filtered_posts__name__iexact='John')
You have look at these,