---
title: "Expressions conditionnelles"
version: 1.9
locale: fr
source: https://docs.djangoproject.com/fr/1.9/ref/models/conditional-expressions/
canonical: https://djangodocs.dev/fr/1.9/ref/models/conditional-expressions/
---
# Expressions conditionnelles

> **New in Django 1.8**

Les expressions conditionnelles permettent d’utiliser de la logique [`if`](https://docs.python.org/3/reference/compound_stmts.html#if) … [`elif`](https://docs.python.org/3/reference/compound_stmts.html#elif) … [`else`](https://docs.python.org/3/reference/compound_stmts.html#else) à l’intérieur des filtres, des annotations, des agrégations et des mises à jour. Une expression conditionnelle évalue une série de conditions pour chaque ligne d’une table et renvoie l’expression résultante correspondante. Les expressions conditionnelles peuvent également être combinées et imbriquées comme toute autre [expression](/fr/1.9/ref/models/expressions/).

## Les classes d’expressions conditionnelles

Nous allons utiliser le modèle suivant dans les exemples qui suivront :

```
from django.db import models

class Client(models.Model):
    REGULAR = 'R'
    GOLD = 'G'
    PLATINUM = 'P'
    ACCOUNT_TYPE_CHOICES = (
        (REGULAR, 'Regular'),
        (GOLD, 'Gold'),
        (PLATINUM, 'Platinum'),
    )
    name = models.CharField(max_length=50)
    registered_on = models.DateField()
    account_type = models.CharField(
        max_length=1,
        choices=ACCOUNT_TYPE_CHOICES,
        default=REGULAR,
    )
```

### `When`

#### `class When(condition=None, then=None, **lookups)`

Un objet `When()` est utilisé pour englober une condition et ses résultats pour leur exploitation dans une expression conditionnelle. L’emploi d’un objet `When()` est semblable à celui d’une méthode [`filter()`](/fr/1.9/ref/models/querysets/#django.db.models.query.QuerySet.filter). La condition peut être indiquée en utilisant des objets de [recherche de champ](/fr/1.9/ref/models/querysets/#field-lookups) ou des objets [`Q`](/fr/1.9/ref/models/querysets/#django.db.models.Q). Le résultat est fourni en utilisant le mot-clé `then`.

Quelques exemples :

```
>>> from django.db.models import When, F, Q
>>> # String arguments refer to fields; the following two examples are equivalent:
>>> When(account_type=Client.GOLD, then='name')
>>> When(account_type=Client.GOLD, then=F('name'))
>>> # You can use field lookups in the condition
>>> from datetime import date
>>> When(registered_on__gt=date(2014, 1, 1),
...      registered_on__lt=date(2015, 1, 1),
...      then='account_type')
>>> # Complex conditions can be created using Q objects
>>> When(Q(name__startswith="John") | Q(name__startswith="Paul"),
...      then='name')
```

N’oubliez pas que chacune de ces valeurs peut être elle-même une expression.

> **Note**
>
> Comme le paramètre nommé `then` est réservé au résultat de l’expression `When()`, un conflit potentiel existe si un [`Model`](/fr/1.9/ref/models/instances/#django.db.models.Model) possède un champ nommé `then`. Ceci peut être résolu de deux manières :
>
> ```
> >>> When(then__exact=0, then=1)
> >>> When(Q(then=0), then=1)
> ```

### `Case`

#### `class Case(*cases, **extra)`

Une expression `Case()` est semblable à une instruction [`if`](https://docs.python.org/3/reference/compound_stmts.html#if) … [`elif`](https://docs.python.org/3/reference/compound_stmts.html#elif) … [`else`](https://docs.python.org/3/reference/compound_stmts.html#else) en Python. Chaque `condition` dans les objets `When()` fournis est évaluée dans l’ordre, jusqu’à ce que l’une d’elle résulte en une valeur vraie. L’expression `result` de l’objet `When()` correspondant est renvoyée.

Un exemple simple :

```
>>>
>>> from datetime import date, timedelta
>>> from django.db.models import CharField, Case, Value, When
>>> Client.objects.create(
...     name='Jane Doe',
...     account_type=Client.REGULAR,
...     registered_on=date.today() - timedelta(days=36))
>>> Client.objects.create(
...     name='James Smith',
...     account_type=Client.GOLD,
...     registered_on=date.today() - timedelta(days=5))
>>> Client.objects.create(
...     name='Jack Black',
...     account_type=Client.PLATINUM,
...     registered_on=date.today() - timedelta(days=10 * 365))
>>> # Get the discount for each Client based on the account type
>>> Client.objects.annotate(
...     discount=Case(
...         When(account_type=Client.GOLD, then=Value('5%')),
...         When(account_type=Client.PLATINUM, then=Value('10%')),
...         default=Value('0%'),
...         output_field=CharField(),
...     ),
... ).values_list('name', 'discount')
[('Jane Doe', '0%'), ('James Smith', '5%'), ('Jack Black', '10%')]
```

`Case()` accepts any number of `When()` objects as individual arguments.
Other options are provided using keyword arguments. If none of the conditions
evaluate to `TRUE`, then the expression given with the `default` keyword
argument is returned. If a `default` argument isn’t provided, `None` is
used.

Si nous voulions modifier notre requête précédente pour obtenir le rabais sur la base de la fidélité de `Client`, nous pourrions le faire à l’aide d’expressions de recherche :

```
>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Get the discount for each Client based on the registration date
>>> Client.objects.annotate(
...     discount=Case(
...         When(registered_on__lte=a_year_ago, then=Value('10%')),
...         When(registered_on__lte=a_month_ago, then=Value('5%')),
...         default=Value('0%'),
...         output_field=CharField(),
...     )
... ).values_list('name', 'discount')
[('Jane Doe', '5%'), ('James Smith', '0%'), ('Jack Black', '10%')]
```

> **Note**
>
> Rappelez-vous que les conditions sont évaluées dans l’ordre, ce qui fait que dans l’exemple ci-dessus, nous obtenons le résultat correct même si la seconde condition correspondait à la fois à Jane Doe et à Jack Black. Cela fonctionne exactement de la même manière qu’avec l’instruction [`if`](https://docs.python.org/3/reference/compound_stmts.html#if) … [`elif`](https://docs.python.org/3/reference/compound_stmts.html#elif) … [`else`](https://docs.python.org/3/reference/compound_stmts.html#else) en Python.

## Requêtes avancées

Les expressions conditionnelles peuvent être utilisées dans les annotations, les agrégations, les recherches et les mises à jour. Elles peuvent également être combinées et imbriquées avec d’autres expressions. Cela permet d’effectuer des requêtes conditionnelles puissantes.

### Mise à jour conditionnelle

Admettons que nous voulions modifier le type de compte `account_type` de nos clients pour qu’il corresponde aux dates d’enregistrement. Nous pouvons le faire à l’aide d’une expression conditionnelle et de la méthode [`update()`](/fr/1.9/ref/models/querysets/#django.db.models.query.QuerySet.update):

```
>>> a_month_ago = date.today() - timedelta(days=30)
>>> a_year_ago = date.today() - timedelta(days=365)
>>> # Update the account_type for each Client from the registration date
>>> Client.objects.update(
...     account_type=Case(
...         When(registered_on__lte=a_year_ago,
...              then=Value(Client.PLATINUM)),
...         When(registered_on__lte=a_month_ago,
...              then=Value(Client.GOLD)),
...         default=Value(Client.REGULAR)
...     ),
... )
>>> Client.objects.values_list('name', 'account_type')
[('Jane Doe', 'G'), ('James Smith', 'R'), ('Jack Black', 'P')]
```

### Agrégation conditionnelle

Et si nous voulions savoir combien de clients existent pour chaque type de compte ? Nous pouvons imbriquer une expression conditionnelle à l’intérieur de [fonctions d’agrégation](/fr/1.9/ref/models/querysets/#aggregation-functions) pour pouvoir faire cela :

```
>>> # Create some more Clients first so we can have something to count
>>> Client.objects.create(
...     name='Jean Grey',
...     account_type=Client.REGULAR,
...     registered_on=date.today())
>>> Client.objects.create(
...     name='James Bond',
...     account_type=Client.PLATINUM,
...     registered_on=date.today())
>>> Client.objects.create(
...     name='Jane Porter',
...     account_type=Client.PLATINUM,
...     registered_on=date.today())
>>> # Get counts for each value of account_type
>>> from django.db.models import IntegerField, Sum
>>> Client.objects.aggregate(
...     regular=Sum(
...         Case(When(account_type=Client.REGULAR, then=1),
...              output_field=IntegerField())
...     ),
...     gold=Sum(
...         Case(When(account_type=Client.GOLD, then=1),
...              output_field=IntegerField())
...     ),
...     platinum=Sum(
...         Case(When(account_type=Client.PLATINUM, then=1),
...              output_field=IntegerField())
...     )
... )
{'regular': 2, 'gold': 1, 'platinum': 3}
```
