summaryrefslogtreecommitdiff
path: root/docs/ref
diff options
context:
space:
mode:
authorNicolas Delaby <ticosax@free.fr>2017-09-22 17:53:17 +0200
committerTim Graham <timograham@gmail.com>2017-09-22 11:53:17 -0400
commit01d440fa1e6b5c62acfa8b3fde43dfa1505f93c6 (patch)
tree21b1f96ecd0fca636746595bce50eb46abdde880 /docs/ref
parent3f9d85d95cab228fd881ea952c707022e9e3bdf3 (diff)
Fixed #27332 -- Added FilteredRelation API for conditional join (ON clause) support.
Thanks Anssi Kääriäinen for contributing to the patch.
Diffstat (limited to 'docs/ref')
-rw-r--r--docs/ref/models/querysets.txt57
1 files changed, 57 insertions, 0 deletions
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index f62050d818..f85ce1e441 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -3318,3 +3318,60 @@ lookups or :class:`Prefetch` objects you want to prefetch for. For example::
>>> from django.db.models import prefetch_related_objects
>>> restaurants = fetch_top_restaurants_from_cache() # A list of Restaurants
>>> prefetch_related_objects(restaurants, 'pizzas__toppings')
+
+``FilteredRelation()`` objects
+------------------------------
+
+.. versionadded:: 2.0
+
+.. class:: FilteredRelation(relation_name, *, condition=Q())
+
+ .. attribute:: FilteredRelation.relation_name
+
+ The name of the field on which you'd like to filter the relation.
+
+ .. attribute:: FilteredRelation.condition
+
+ A :class:`~django.db.models.Q` object to control the filtering.
+
+``FilteredRelation`` is used with :meth:`~.QuerySet.annotate()` to create an
+``ON`` clause when a ``JOIN`` is performed. It doesn't act on the default
+relationship but on the annotation name (``pizzas_vegetarian`` in example
+below).
+
+For example, to find restaurants that have vegetarian pizzas with
+``'mozzarella'`` in the name::
+
+ >>> from django.db.models import FilteredRelation, Q
+ >>> Restaurant.objects.annotate(
+ ... pizzas_vegetarian=FilteredRelation(
+ ... 'pizzas', condition=Q(pizzas__vegetarian=True),
+ ... ),
+ ... ).filter(pizzas_vegetarian__name__icontains='mozzarella')
+
+If there are a large number of pizzas, this queryset performs better than::
+
+ >>> Restaurant.objects.filter(
+ ... pizzas__vegetarian=True,
+ ... pizzas__name__icontains='mozzarella',
+ ... )
+
+because the filtering in the ``WHERE`` clause of the first queryset will only
+operate on vegetarian pizzas.
+
+``FilteredRelation`` doesn't support:
+
+* Conditions that span relational fields. For example::
+
+ >>> Restaurant.objects.annotate(
+ ... pizzas_with_toppings_startswith_n=FilteredRelation(
+ ... 'pizzas__toppings',
+ ... condition=Q(pizzas__toppings__name__startswith='n'),
+ ... ),
+ ... )
+ Traceback (most recent call last):
+ ...
+ ValueError: FilteredRelation's condition doesn't support nested relations (got 'pizzas__toppings__name__startswith').
+* :meth:`.QuerySet.only` and :meth:`~.QuerySet.prefetch_related`.
+* A :class:`~django.contrib.contenttypes.fields.GenericForeignKey`
+ inherited from a parent model.