diff options
| author | Nicolas Delaby <ticosax@free.fr> | 2017-09-22 17:53:17 +0200 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2017-09-22 11:53:17 -0400 |
| commit | 01d440fa1e6b5c62acfa8b3fde43dfa1505f93c6 (patch) | |
| tree | 21b1f96ecd0fca636746595bce50eb46abdde880 /docs/ref | |
| parent | 3f9d85d95cab228fd881ea952c707022e9e3bdf3 (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.txt | 57 |
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. |
