# Documentation Django 6.0.7

# Référence de l’API `QuerySet`

Ce document détaille l’API des objets `QuerySet`. Il augmente les contenus présentés dans les guides des modèles et des requêtes de base de données, il est donc conseillé de lire et de comprendre ces derniers avant de lire celui-ci.

Tout au long de cette référence, nous utiliserons les modèles d’exemple de blog présentés dans le guide des requêtes de base de données.

## Quand les objets `QuerySet` sont évalués

En interne, un objet `QuerySet` peut être construit, filtré, segmenté ou transmis sans devoir accéder à la base de données. Aucune activité de base de données n’est effectivement créée tant qu’une action ne provoque pas l’évaluation du jeu de requête.

Un `QuerySet` est évalué dans les contextes suivants :

- Itération. Un `QuerySet` est itérable, et il exécute sa requête de base de données lors de la première itération. Par exemple, ceci affiche le titre de tous les articles de la base de données :

      for e in Entry.objects.all():
          print(e.headline)

  Note : ne faites pas cela si vous voulez uniquement savoir s’il existe au moins un résultat. Il est plus efficace d’utiliser `exists()`.

- Itération asynchrone. Il est aussi possible d’itérer sur un `QuerySet` en utilisant `async for`:

      async for e in Entry.objects.all():
          results.append(e)

  Les itérateurs de `QuerySet` synchrones et asynchrones partagent le même cache sous-jacent.

- Segmentation. Comme expliqué dans Limitation des QuerySet, un `QuerySet` peut être segmenté par la syntaxe de segmentation de liste de Python. La segmentation d’un `QuerySet` non évalué renvoie habituellement un autre objet `QuerySet` non évalué, mais Django exécute la requête de base de données si vous employez le paramètre `step` de la syntaxe de segmentation, et dans ce cas, une liste est renvoyée. La segmentation d’un `QuerySet` qui a été évalué renvoie également une liste.

  Notez également que bien que la segmentation d’un objet `QuerySet` non évalué renvoie un autre `QuerySet` non évalué, sa modification ultérieure (par ex. par l’ajout de filtres ou en modifiant l’ordre de tri) n’est plus permise, car cela se traduirait difficilement en termes SQL et la signification d’une telle opération ne serait pas claire non plus.

- « Pickling »/mise en cache. Consultez la section suivante pour plus de détails sur les implications du « pickling » des objets QuerySets. L’élément important dans la perspective de cette section est que les résultats sont lus à partir de la base de données.

- repr(). Un `QuerySet` est évalué lorsqu’on l’inclut dans un appel `repr()`. Ceci pour des raisons pratiques dans l’interpréteur interactif Python, afin de pouvoir visualiser immédiatement les résultats en utilisant l’API de manière interactive.

- len(). Un `QuerySet` est évalué lorsqu’on l’inclut dans un appel `len()`. Ceci renvoie comme prévu la longueur de la liste résultante.

  Note : si vous avez seulement besoin de connaître le nombre d’enregistrements du résultat (et que vous n’avez pas besoin des objets eux-mêmes), il est bien plus efficace de gérer la comptabilisation au niveau de la base de données en utilisant le code SQL `SELECT COUNT(*)`. Django fournit une méthode `count()` précisément pour cette raison.

- list(). Force l’évaluation d’un `QuerySet` lorsqu’on l’inclut dans un appel `list()`. Par exemple :

      entry_list = list(Entry.objects.all())

- bool(). Le test d’un `QuerySet` dans un contexte booléen, comme par exemple en employant `bool()`, `or`, `and` ou `if`, va provoquer l’exécution de la requête. S’il existe au moins un résultat, le `QuerySet` renverra `True`, sinon `False`. Par exemple :

      if Entry.objects.filter(headline="Test"):
          print("There is at least one Entry with the headline Test")

  Note : si tout ce qui vous intéresse est de déterminer s’il existe au moins un résultat (et que vous n’avez pas besoin des objets eux-mêmes), il est plus efficace d’utiliser `exists()`.

### `QuerySet` et « pickling »

Si vous transformez un `QuerySet` par `pickle`, cela force tous les résultats à être chargés en mémoire avant le processus de pickling. Cette opération précède généralement une mise en cache, et lorsque le jeu de requête est récupéré du cache, il est souhaitable que les résultats soient disponibles et prêts à être utilisés (une lecture depuis la base de données peut prendre du temps, ce qui annulerait l’avantage du cache). Cela signifie que lorsqu’un objet `QuerySet` est reconstruit depuis sa représentation « pickle », il contient les résultats du moment où il a été transformé par « pickle », et non pas les résultats du moment actuel en base de données.

Si vous ne vouliez que mettre en « pickle » les informations utiles pour recréer le `QuerySet` à partir de la base de données au moment voulu, fournissez à pickle l’attribut `query` de `QuerySet`. Vous pouvez ensuite recréer le `QuerySet` original (sans chargement des résultats) en écrivant du code semblable à ceci :

    >>> import pickle
    >>> query = pickle.loads(s)  # Assuming 's' is the pickled string.
    >>> qs = MyModel.objects.all()
    >>> qs.query = query  # Restore the original 'query'.

L’attribut `query` est un objet opaque. Il constitue la représentation interne de la construction de la requête et ne fait pas partie de l’API publique. Cependant, la sérialisation et la désérialisation « pickle » du contenu de cet attribut est une opération sûre (et totalement acceptable).

Restrictions avec `QuerySet.values_list()`

Si vous recréez `QuerySet.values_list()` en utilisant l’attribut `query` sérialisé par « pickle », il sera converti en résultat `QuerySet.values()`:

    >>> import pickle
    >>> qs = Blog.objects.values_list("id", "name")
    >>> qs
    <QuerySet [(1, 'Beatles Blog')]>
    >>> reloaded_qs = Blog.objects.all()
    >>> reloaded_qs.query = pickle.loads(pickle.dumps(qs.query))
    >>> reloaded_qs
    <QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

Il n’est pas possible de partager des sérialisations « pickle » entre différentes versions

Des sérialisations « pickle » des objets `QuerySet` ne sont valables que pour la version de Django utilisée pour les générer. Si vous produisez du contenu « pickle » avec une version N de Django, il n’y a aucune garantie que ce contenu soit lisible par une version N+1 de Django. La sérialisation « pickle » ne doit pas être utilisée dans le cadre d’une stratégie d’archivage à long terme.

Comme des erreurs de compatibilité de pickle peuvent être difficiles à diagnostiquer, comme par exemple des objets silencieusement corrompus, un avertissement `RuntimeWarning` est produit si vous essayez de désérialiser un jeu de requête dans une version de Django différente de celle qui a été utilisée pour la sérialisation.

## API `QuerySet`

Voici la déclaration formelle d’un `QuerySet`:

class QuerySet(model=None, query=None, using=None, hints=None)

  Normalement, lorsqu’on manipule un `QuerySet`, on le fait en enchaînant des filtres. Pour accomplir cela, la plupart des méthodes de `QuerySet` renvoient de nouveaux objets `QuerySet`. Ces méthodes sont décrites en détails plus loin dans cette section.

  La classe `QuerySet` possède les attributs publics suivants qu’il est possible d’utiliser pour introspection :

  ordered

    `True` si le `QuerySet` est trié, c’est-à-dire qu’il comporte une clause `order_by()` ou un tri par défaut au niveau du modèle. Sinon, la valeur est `False`.

  totally_ordered
    New in Django 6.1.

    Returns `True` if the `QuerySet` is ordered and the ordering is deterministic. This requires that the ordering includes a field (or set of fields) that is unique and non-nullable.

    For queries involving a `GROUP BY` clause, the model’s default ordering is ignored. Ordering specified via `.extra(order_by=...)` is also ignored.

  db

    La base de données utilisée si la requête est exécutée tout de suite.

  Note

  Le paramètre `query` de `QuerySet` existe pour que des sous-classes spécialisées puissent reconstruire l’état interne des requêtes. La valeur du paramètre est une représentation opaque de l’état de la requête et ne fait pas partie de l’API publique.

### Méthodes renvoyant de nouveaux `QuerySet`

Django fournit un grand nombre de méthodes d’affinage des `QuerySet` qui modifient soit le type de résultats renvoyés par le `QuerySet` ou sa façon d’exécuter la requête SQL.

Note

Ces méthodes n’exécutent pas de requête en base de données, elles sont donc utilisables sans problème dans du code asynchrone, et ne possèdent dès lors pas de version asynchrone distincte.

#### `filter()`

filter(*args, **kwargs)

Renvoie un nouveau `QuerySet` contenant les objets qui répondent aux paramètres de recherche donnés.

Les paramètres de recherche (`**kwargs`) doivent être dans le format décrit dans Recherches dans les champs ci-dessous. Plusieurs paramètres sont combinés via `AND` dans l’instruction SQL sous-jacente.

If you need to execute more complex queries (for example, queries with `OR` statements), you can use Objets Q() (`*args`).

#### `exclude()`

exclude(*args, **kwargs)

Renvoie un nouveau `QuerySet` contenant les objets qui ne répondent pas aux paramètres de recherche donnés.

Les paramètres de recherche (`**kwargs`) doivent être dans le format décrit dans Recherches dans les champs ci-dessous. Plusieurs paramètres sont combinés via `AND` dans l’instruction SQL sous-jacente, et le tout est englobé dans un `NOT()`.

Cet exemple exclut tous les éléments dont `pub_date` est postérieure à 2005-1-3 ET dont `headline` contient « Hello » :

    Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline="Hello")

En termes SQL, cela donne :

    SELECT ...
    WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')

Cet exemple exclut tous les éléments dont `pub_date` est postérieure à 2005-1-3 OU dont `headline` contient « Hello »

    Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline="Hello")

En termes SQL, cela donne :

    SELECT ...
    WHERE NOT pub_date > '2005-1-3'
    AND NOT headline = 'Hello'

Notez que le second exemple est plus restrictif.

Si vous avez besoin d’exécuter des requêtes plus complexes (par exemple des requêtes contenant des instruction avec `OR` (OU)), vous pouvez utiliser des `objets Q` (`*args`).

#### `annotate()`

annotate(*args, **kwargs)

Annotates each object in the `QuerySet` with the provided list of query expressions or Objets Q(). Each object can be annotated with:

- une valeur simple, via `Value()` ;

- une référence à un champ du modèle (ou tout modèle lié), via `F()` ;

- une valeur booléenne, via `Q()` ; ou

- un résultat d’un expression d’agrégat (moyennes, sommes, etc.) calculée sur les objets qui sont liés aux objets du `QuerySet`.

Chaque paramètre d’`annotate()` est une annotation qui sera ajoutée à chaque objet du `QuerySet` renvoyé.

Les fonctions d’agrégation fournies par Django sont décrites plus loin dans Fonctions d’agrégation.

Les annotations spécifiées par des paramètres nommés utilisent la clé comme alias d’annotation. Les paramètres anonymes seront dotés d’un alias généré automatiquement sur la base du nom de la fonction d’agrégation et du champ de modèle sur lequel porte l’agrégation. Seules les expressions d’agrégation qui font référence à un seul champ peuvent constituer des paramètres anonymes. Tout le reste doit se présenter sous la forme d’un paramètre nommé.

Par exemple, si vous avez affaire à une liste de blogs, il peut être intéressant de déterminer le nombre d’articles écrits dans chaque blog :

    >>> from django.db.models import Count
    >>> q = Blog.objects.annotate(Count("entry"))
    # The name of the first blog
    >>> q[0].name
    'Blogasaurus'
    # The number of entries on the first blog
    >>> q[0].entry__count
    42

Le modèle `Blog` ne définit pas d’attribut `entry__count` par lui-même, mais en utilisant un paramètre nommé pour définir la fonction d’agrégation, vous pouvez contrôler le nom de l’annotation :

    >>> q = Blog.objects.annotate(number_of_entries=Count("entry"))
    # The number of entries on the first blog, using the name provided
    >>> q[0].number_of_entries
    42

Pour une présentation approfondie de l’agrégation, consultez le guide thématique sur l’agrégation.

#### `alias()`

alias(*args, **kwargs)

Semblable à `annotate()`, mais au lieu d’annoter les objets de `QuerySet`, enregistre l’expression pour être réutilisée avec d’autres méthodes `QuerySet`. Cela est utile lorsque le résultat de l’expression lui-même n’est pas utile au final, mais uniquement employé pour filtrer, trier ou comme faisant partie d’une expression complexe. Le fait de ne pas sélectionner cette valeur non utile enlève du travail redondant au niveau de la base de données et devrait aboutir à de meilleures performances.

Par exemple, si vous souhaitez trouver des blogs avec mois de 5 articles, mais que le nombre exact d’articles ne vous intéresse pas, vous pourriez écrire ceci :

    >>> from django.db.models import Count
    >>> blogs = Blog.objects.alias(entries=Count("entry")).filter(entries__gt=5)

`alias()` can be used in conjunction with `annotate()`, `exclude()`, `filter()`, `order_by()`, and `update()`. To use an aliased expression with other methods (e.g. `aggregate()`), you must promote it to an annotation:

    Blog.objects.alias(entries=Count("entry")).annotate(
        entries=F("entries"),
    ).aggregate(Sum("entries"))

`filter()` and `order_by()` can take expressions directly, but expression construction and usage often does not happen in the same place (for example, `QuerySet` method creates expressions, for later use in views). `alias()` allows building complex expressions incrementally (possibly spanning multiple methods and modules), referring to the expression parts by their aliases, and only using `annotate()` for the final result.

#### `order_by()`

order_by(*fields)

Par défaut, les résultats renvoyés par un `QuerySet` sont triés selon le tuple de tri défini par l’option `ordering` de la classe `Meta` du modèle. Vous pouvez surcharger cela pour chaque `QuerySet` en utilisant la méthode `order_by`.

Exemple :

    Entry.objects.filter(pub_date__year=2005).order_by("-pub_date", "headline")

Les résultats ci-dessus seront triés par `pub_date` dans l’ordre chronologique inverse, puis par `headline` dans l’ordre alphabétique. Le signe moins devant `"-pub_date"` indique l”inversion de l’ordre de tri. Pour trier de manière aléatoire, utilisez `"?"` comme ceci :

    Entry.objects.order_by("?")

Note : les requêtes `order_by('?')` peuvent être coûteuses et lentes, en fonction du moteur de base de données utilisé.

Pour trier selon un champ d’un autre modèle, utilisez la même syntaxe que lorsque vous interrogez la base de données en traversant des relations. C’est-à-dire, le nom du champ suivi d’un double soulignement (`__`), suivi du nom du champ du nouveau modèle, et ainsi de suite pour autant de modèles que vous souhaitez combiner. Par exemple :

    Entry.objects.order_by("blog__name", "headline")

Si vous essayez de trier selon un champ qui constitue une relation vers un autre modèle, Django utilise le tri par défaut du modèle lié, ou trie selon la clé primaire du modèle lié si aucun attribut `Meta.ordering` n’est présent. Par exemple, comme le modèle `Blog` ne possède par d’ordre de tri par défaut :

    Entry.objects.order_by("blog")

… est identique à :

    Entry.objects.order_by("blog__id")

Si `Blog` comportait `ordering = ['name']`, alors le premier jeu de requête serait identique à :

    Entry.objects.order_by("blog__name")

Il est aussi possible de trier par des expressions de requête en appelant `asc()` ou `desc()` sur l’expression :

    Entry.objects.order_by(Coalesce("summary", "headline").desc())

`asc()` et `desc()` possèdent des paramètres (`nulls_first` and `nulls_last`) qui contrôlent la manière dont sont triées les valeurs nulles.

Soyez prudent lorsque vous triez selon des champs de modèles liés et que vous utilisez également `distinct()`. Consultez la note dans `distinct()` pour une explication sur l’impact possible du tri selon des modèles liés sur les résultats attendus.

Note

Il est autorisé de définir un champ multivalué comme critère de tri (par exemple, un champ `ManyToManyField` ou la relation inverse d’un champ `ForeignKey`).

Considérez ce cas :

    class Event(Model):
        parent = models.ForeignKey(
            "self",
            on_delete=models.CASCADE,
            related_name="children",
        )
        date = models.DateField()

    Event.objects.order_by("children__date")

Dans ce cas, il est possible que plusieurs données de tri existent pour chaque `Event`. Un `Event` avec plusieurs `children` sera renvoyé plusieurs fois dans le nouveau `QuerySet` créé par `order_by()`. En d’autres termes, l’application de `order_by()` sur le `QuerySet` peut renvoyer plus d’éléments que l’ensemble de départ, ce qui n’est ni le résultat attendu, ni utile.

Ainsi, il faut être très prudent lorsqu’on utilise un champ multivalué pour trier des résultats. Si vous pouvez être certain qu’il n’y aura qu’une donnée de tri pour chaque élément que vous triez, cette approche ne devrait pas poser de problème. Dans le cas contraire, vérifiez soigneusement que les résultats correspondent à votre attente.

Il n’est pas possible d’indiquer si le tri doit être sensible à la casse ou non. Dans cette optique, Django trie les résultats en fonction du comportement habituel de tri du moteur de base de données.

Vous pouvez trier selon un champ converti en minuscules avec `Lower`, ce qui aboutira à un tri insensible à la casse :

    Entry.objects.order_by(Lower("headline").desc())

Si vous ne voulez pas qu’une requête soit triée, même pas selon le tri par défaut, appelez `order_by()` sans paramètre.

Vous pouvez savoir si une requête est triée ou pas en interrogeant l’attribut `QuerySet.ordered`, qui vaut `True` lorsque le `QuerySet` a été trié d’une manière ou d’une autre.

Chaque appel à `order_by()` efface tout ordre de tri préexistant. Par exemple, cette requête sera triée par `pub_date` et non pas par `headline`:

    Entry.objects.order_by("headline").order_by("pub_date")

Avertissement

Le tri n’est pas une opération anodine. Chaque champ ajouté dans les critères de tri implique un coût au niveau de la base de données. Chaque clé étrangère ajoutée inclut aussi implicitement tous ses champs de tri par défaut.

Si une requête ne possède pas d’ordre de tri, les résultats sont renvoyés de la base de données dans un ordre non défini. Un ordre particulier ne peut être garanti que si l’ordre se base sur un ou des champs qui identifient chaque objet du résultat de manière unique. Par exemple, si un champ `nom` n’est pas unique, le tri par ce champ ne garantit pas que les objets de même nom apparaissent toujours dans le même ordre.

#### `reverse()`

reverse()

Utilisez la méthode `reverse()` pour inverser l’ordre dans lequel les éléments d’un jeu de requête sont renvoyés. En appelant `reverse()` une seconde fois, l’ordre est rétabli selon l’ordre initial normal.

Pour récupérer les cinq « derniers » éléments d’un jeu de requête, vous pourriez écrire cela :

    my_queryset.reverse()[:5]

Notez que ce n’est pas tout à fait la même chose que de segmenter à partir de la fin d’une liste en Python. L’exemple ci-dessus renvoie en premier le dernier élément, puis l’avant-dernier et ainsi de suite. Si nous avions une liste Python et que nous avions appliqué `list[-5:]`, nous aurions obtenu les 5 derniers éléments. Django ne prend pas en charge ce mode d’accès avec les jeux de requête (segmentation à partir de la fin), car il n’est pas possible de le faire efficacement en SQL.

Signalons également que `reverse()` ne devrait généralement être appelé que pour un `QuerySet` dont l’ordre de tri est défini (par exemple, lors d’une requête sur un modèle définissant un tri par défaut ou en appelant `order_by()`). Si un `QuerySet` donné ne comporte pas d’ordre de tri, l’appel `reverse()` sur cet objet n’a pas d’effet réel (le tri n’étant pas défini avant l’appel à `reverse()`, il ne le sera pas plus après).

#### `distinct()`

distinct(*fields)

Renvoie un nouveau `QuerySet` utilisant `SELECT DISTINCT` dans sa requête SQL. Les lignes dupliquées sont alors supprimées des résultats de la requête.

Par défaut, un `QuerySet` n’élimine pas les lignes dupliquées. En pratique, c’est rarement un problème, car les requêtes simples comme `Blog.objects.all()` n’introduisent pas la possibilité de lignes de résultats dupliquées. Cependant, si la requête s’étend sur plusieurs tables, il est possible d’obtenir des résultats dupliqués lors de l’évaluation du `QuerySet`. C’est alors que `distinct()` devient utile.

Note

Tout champ mentionné dans un appel `order_by()` est inclus dans les colonnes `SELECT` de l’instruction SQL. Cela peut parfois amener à des résultats inattendus lors d’une utilisation conjointe avec `distinct()`. Si vous triez en fonction de champs d’un modèle lié, ces champs seront ajoutés aux colonnes sélectionnées et certaines lignes qui seraient normalement dupliquées (donc supprimées) apparaissent alors comme distinctes. Comme ces colonnes supplémentaires n’apparaissent pas dans les résultats renvoyés (elles ne servent qu’au tri), il peut sembler que des lignes dupliquées, non distinctes sont renvoyées malgré tout.

De même, si vous utilisez une requête `values()` pour limiter les colonnes sélectionnées, toute colonne mentionnée dans `order_by()` (ou dans un tri par défaut d’un modèle) fera tout de même partie de la requête et pourrait interférer avec l’unicité des résultats.

La morale à retenir est que si vous utilisez `distinct()`, vous devez rester prudent lors des tris selon des modèles liés. De même, lorsque vous combinez l’utilisation de `distinct()` et de `values()`, soyez prudent avec les champs de tri qui ne figurent pas dans l’appel à `values()`.

Avec PostgreSQL uniquement, vous pouvez transmettre des paramètres positionnels (`*fields`) afin de préciser les noms des champs sur lesquels l’instruction `DISTINCT` s’applique. Cela produit une requête SQL du genre `SELECT DISTINCT ON`. Voici la différence. Pour un appel `distinct()` normal, la base de données compare chaque champ de chaque ligne pour déterminer quelles lignes sont distinctes. Lors d’un appel `distinct()` qui spécifie des noms de champs, la base de données ne compare que les champs indiqués pour déterminer les lignes distinctes.

Note

Lorsque vous indiquez des noms de champs, vous devez fournir une clause `order_by()` pour le `QuerySet`, et les champs dans `order_by()` doivent commencer par les champs de `distinct()`, dans le même ordre.

Par exemple, `SELECT DISTINCT ON (a)` renvoie la première ligne pour chaque valeur différente dans la colonne `a`. Si vous n’indiquez pas de tri, le choix de la ligne renvoyée est arbitraire.

Exemples (à partir du deuxième exemple, cela ne fonctionne qu’avec PostgreSQL) :

    >>> Author.objects.distinct()
    <QuerySet [...]>
    >>> Entry.objects.order_by("pub_date").distinct("pub_date")
    <QuerySet [...]>
    >>> Entry.objects.order_by("blog").distinct("blog")
    <QuerySet [...]>
    >>> Entry.objects.order_by("author", "pub_date").distinct("author", "pub_date")
    <QuerySet [...]>
    >>> Entry.objects.order_by("blog__name", "mod_date").distinct("blog__name", "mod_date")
    <QuerySet [...]>
    >>> Entry.objects.order_by("author", "pub_date").distinct("author")
    <QuerySet [...]>

Note

Gardez en tête que `order_by()` utilise les éventuels ordres de tri par défaut définis pour les modèles liés. Il peut être nécessaire de trier explicitement selon le nom `_id` de la relation ou selon le champ référencé pour s’assurer que les expressions `DISTINCT ON` correspondent à celles du début de la clause `ORDER BY`. Par exemple, si le modèle `Blog` définit un tri `ordering` selon son champ `name`:

    Entry.objects.order_by("blog").distinct("blog")

…ne fonctionnera pas car la requête serait triée par `blog__name` et ne correspondra donc pas à l’expression `DISTINCT ON`. Il faudrait trier explicitement selon le champ `_id` de la relation (`blog_id` dans ce cas) ou selon le champ référencé (`blog__pk`) pour être certain que les deux expressions correspondent.

#### `values()`

values(*fields, **expressions)

Renvoie un `QuerySet` qui renvoie des dictionnaires lorsqu’on l’utilise de manière itérable, au lieu d’instances de modèles.

Chacun de ces dictionnaires représente un objet, les clés correspondant aux noms d’attributs des objets de modèle.

Cet exemple compare les dictionnaires de `values()` avec des objets de modèle normaux :

    # This list contains a Blog object.
    >>> Blog.objects.filter(name__startswith="Beatles")
    <QuerySet [<Blog: Beatles Blog>]>

    # This list contains a dictionary.
    >>> Blog.objects.filter(name__startswith="Beatles").values()
    <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>

La méthode `values()` accepte des paramètres positionnels facultatifs, `*fields`, qui définissent les noms de champs auxquels l’instruction `SELECT` se limitera. Si vous renseignez ces paramètres, chaque dictionnaire du résultat ne contiendra que les clés/valeurs des champs qui ont été indiqués. Si aucun de ces paramètres n’est présent, chaque dictionnaire du résultat contiendra une clé et une valeur pour tous les champs de la table de base de données correspondante.

Exemple :

    >>> Blog.objects.values()
    <QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
    >>> Blog.objects.values("id", "name")
    <QuerySet [{'id': 1, 'name': 'Beatles Blog'}]>

La méthode `values()` accepte également des paramètres nommés facultatifs, `**expressions`, qui sont transmis par `annotate()`:

    >>> from django.db.models.functions import Lower
    >>> Blog.objects.values(lower_name=Lower("name"))
    <QuerySet [{'lower_name': 'beatles blog'}]>

Vous pouvez utiliser les requêtes intégrées ou personnalisées dans les tris. Par exemple :

    >>> from django.db.models import CharField
    >>> from django.db.models.functions import Lower
    >>> CharField.register_lookup(Lower)
    >>> Blog.objects.values("name__lower")
    <QuerySet [{'name__lower': 'beatles blog'}]>

Une agrégation à l’intérieur d’une clause `values()` est appliquée avant les autres paramètres dans la même clause. Si vous avez besoin de grouper selon une autre valeur, ajoutez-la plutôt à une clause `values()` précédente. Par exemple :

    >>> from django.db.models import Count
    >>> Blog.objects.values("entry__authors", entries=Count("entry"))
    <QuerySet [{'entry__authors': 1, 'entries': 20}, {'entry__authors': 1, 'entries': 13}]>
    >>> Blog.objects.values("entry__authors").annotate(entries=Count("entry"))
    <QuerySet [{'entry__authors': 1, 'entries': 33}]>

Quelques subtilités qui valent la peine d’être mentionnées :

- Si un champ appelé `foo` est un champ `ForeignKey`, l’appel `values()` par défaut renvoie une clé de dictionnaire nommée `foo_id`, car il s’agit du nom interne de l’attribut de modèle stockant la valeur réelle (l’attribut `foo` se référant au modèle lié). Lorsque vous appelez `values()` et que vous indiquez des noms de champs, vous pouvez mentionner `foo` ou `foo_id` et vous obtiendrez le même résultat (la clé de dictionnaire correspond au nom du champ que vous avez mentionné).

  Par exemple :

      >>> Entry.objects.values()
      <QuerySet [{'blog_id': 1, 'headline': 'First Entry', ...}, ...]>

      >>> Entry.objects.values("blog")
      <QuerySet [{'blog': 1}, ...]>

      >>> Entry.objects.values("blog_id")
      <QuerySet [{'blog_id': 1}, ...]>

- Lors d’une utilisation combinée de `values()` et de `distinct()`, soyez conscient que le tri peut affecter les résultats. Consultez la note dans `distinct()` pour plus de détails.

- Si vous utilisez une clause `values()` après un appel à `extra()`, tout champ mentionné dans un paramètre `select` de `extra()` doit être explicitement inclus dans l’appel à `values()`. Lors de tout appel à `extra()` après un appel à `values()`, les champs sélectionnés supplémentaires sont ignorés.

- Les appels à `only()` et `defer()` après `values()` n’ont pas de sens, et si vous le faites, vous obtiendrez une exception `TypeError`.

- La combinaison de transformations et d’agrégats nécessite l’emploi de deux appels à `annotate()`, soit explicitement ou sous forme de paramètres nommés à meth:values. Comme ci-dessus, si la transformation a été inscrite pour le type de champ adéquat, le premier appel à `annotate()` peut être omis, ce qui signifie que les deux exemples suivants sont équivalents :

      >>> from django.db.models import CharField, Count
      >>> from django.db.models.functions import Lower
      >>> CharField.register_lookup(Lower)
      >>> Blog.objects.values("entry__authors__name__lower").annotate(entries=Count("entry"))
      <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
      >>> Blog.objects.values(entry__authors__name__lower=Lower("entry__authors__name")).annotate(
      ...     entries=Count("entry")
      ... )
      <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>
      >>> Blog.objects.annotate(entry__authors__name__lower=Lower("entry__authors__name")).values(
      ...     "entry__authors__name__lower"
      ... ).annotate(entries=Count("entry"))
      <QuerySet [{'entry__authors__name__lower': 'test author', 'entries': 33}]>

C’est utile lorsque vous savez que vous n’aurez besoin que d’un petit nombre des champs disponibles et que vous n’aurez pas besoin des fonctionnalités d’un objet d’instance de modèle. Il est plus efficace de ne sélectionner que les champs dont vous aurez besoin.

Enfin, notez que vous pouvez appeler `filter()`, `order_by()`, etc. après l’appel à `values()`, ce qui signifie que ces deux appels sont identiques :

    Blog.objects.values().order_by("id")
    Blog.objects.order_by("id").values()

Les concepteurs de Django préfèrent placer en premier les méthodes affectant le code SQL, suivies (facultativement) par toute méthode affectant le format (comme `values()`), mais ce n’est pas essentiel. C’est l’occasion de mettre en évidence votre individualisme.

Vous pouvez aussi faire référence à des modèles liés par des relations inverses au travers d’attributs `OneToOneField`, `ForeignKey` et `ManyToManyField`:

    >>> Blog.objects.values("name", "entry__headline")
    <QuerySet [{'name': 'My blog', 'entry__headline': 'An entry'},
         {'name': 'My blog', 'entry__headline': 'Another entry'}, ...]>

Avertissement

Comme les attributs `ManyToManyField` et les relations inverses peuvent posséder plusieurs lignes liées, leur inclusion peut produire un effet multiplicateur sur la taille du jeu de résultats. Et plus il y a de tels champs dans la requête `values()`, plus l’effet est prononcé, car toutes les combinaisons possibles sont effectuées et renvoyées.

Valeurs spéciales pour `JSONField` avec SQLite

En raison de l’implémentation par SQLite des fonctions SQL `JSON_EXTRACT` et `JSON_TYPE` et de l’absence du type de données booléen, `values()` renvoie `True`, `False` et `None` au lieu des chaînes `"true"`, `"false"` et `"null"` pour les transformations de clés `JSONField`.

#### `values_list()`

values_list(*fields, flat=False, named=False)

Semblable à `values()`, sauf qu’au lieu de renvoyer des dictionnaires, ce sont des tuples qui sont renvoyés lors de l’itération des résultats. Chaque tuple contient les valeurs des champs ou expressions dans la position respective de leur apparition dans l’appel à `values_list()` — premier champ comme premier élément, etc. Par exemple :

    >>> Entry.objects.values_list("id", "headline")
    <QuerySet [(1, 'First entry'), ...]>
    >>> from django.db.models.functions import Lower
    >>> Entry.objects.values_list("id", Lower("headline"))
    <QuerySet [(1, 'first entry'), ...]>

Si vous n’indiquez qu’un seul champ, il est aussi possible d’indiquer le paramètre `flat`. S’il vaut `True`, cela signifie que les résultats renvoyés sont des valeurs uniques au lieu de tuples à un seul élément. Cet exemple devrait éclairer la différence :

    >>> Entry.objects.values_list("id").order_by("id")
    <QuerySet[(1,), (2,), (3,), ...]>

    >>> Entry.objects.values_list("id", flat=True).order_by("id")
    <QuerySet [1, 2, 3, ...]>

C’est une erreur d’indiquer le paramètre `flat` lorsqu’il y a plus d’un champ.

Vous pouvez passer `named=True` pour obtenir les résultats sous forme de `namedtuple()`:

    >>> Entry.objects.values_list("id", "headline", named=True)
    <QuerySet [Row(id=1, headline='First entry'), ...]>

L’emploi d’un tuple nommé peut rendre les résultats plus lisibles, aux dépends d’une petite perte de performance pour la transformation des résultats en tuple nommé.

Si vous n’indiquez aucune valeur dans `values_list()`, tous les champs du modèle sont pris en compte dans le résultat, dans leur ordre de déclaration.

Un besoin fréquent est d’obtenir une valeur de champ spécifique d’une certaine instance de modèle. Pour faire cela, utilisez `values_list()` suivie d’un appel à `get()`:

    >>> Entry.objects.values_list("headline", flat=True).get(pk=1)
    'First entry'

`values()` et `values_list()` doivent toutes deux être considérées comme des optimisations pour un cas d’utilisation spécifique : récupérer un sous-ensemble de données sans la surcharge de création des instances de modèles. Cette métaphore ne vaut plus lorsqu’on a affaire à des relations plusieurs-à-plusieurs ou multivaluées d’une autre manière. (comme la relation un-à-plusieurs d’une clé étrangère inverse) car la supposition « une ligne, un objet » ne tient plus.

Par exemple, remarquez le comportement lorsqu’une requête traverse un champ `ManyToManyField`:

    >>> Author.objects.values_list("name", "entry__headline")
    <QuerySet [('Noam Chomsky', 'Impressions of Gaza'),
     ('George Orwell', 'Why Socialists Do Not Believe in Fun'),
     ('George Orwell', 'In Defence of English Cooking'),
     ('Don Quixote', None)]>

Les auteurs avec plusieurs `Entry` apparaissent plusieurs fois et les auteurs sans `Entry` possèdent `None` comme valeur de ce champ.

De la même façon, lors d’une requête par clé étrangère inverse, `None` apparaît pour les entrées sans auteur :

    >>> Entry.objects.values_list("authors")
    <QuerySet [('Noam Chomsky',), ('George Orwell',), (None,)]>

Valeurs spéciales pour `JSONField` avec SQLite

En raison de l’implémentation par SQLite des fonctions SQL `JSON_EXTRACT` et `JSON_TYPE` et de l’absence du type de données booléen, `values_list()` renvoie `True`, `False` et `None` au lieu des chaînes `"true"`, `"false"` et `"null"` pour les transformations de clés `JSONField`.

#### `dates()`

dates(field, kind, order='ASC')

Renvoie un `QuerySet` dont l’évaluation produit une liste d’objets `datetime.date` représentant toutes les dates disponibles d’un type particulier dans le contenu `QuerySet`.

`field` doit être le nom d’un champ `DateField` du modèle. `kind` doit être soit `"year"`, `"month"`, `"week"` ou `"day"`. Chaque objet `datetime.date` de la liste de résultats est « tronqué » selon le `type` donné.

- `"year"` renvoie une liste de toutes les valeurs d’années distinctes pour le champ.

- `"month"` renvoie une liste de toutes les valeurs d’années/mois distinctes pour le champ.

- `"week"` renvoie une liste de toutes les valeurs d’années/semaines distinctes pour le champ. Toutes les dates sont un lundi.

- `"day"` renvoie une liste de toutes les valeurs d’années/mois/jours distinctes pour le champ.

`order`, dont la valeur par défaut est `'ASC'`, doit contenir soit `'ASC'` (chronologique), soit `'DESC'` (chronologique inverse). Cela indique comment trier les résultats.

Exemples :

    >>> Entry.objects.dates("pub_date", "year")
    [datetime.date(2005, 1, 1)]
    >>> Entry.objects.dates("pub_date", "month")
    [datetime.date(2005, 2, 1), datetime.date(2005, 3, 1)]
    >>> Entry.objects.dates("pub_date", "week")
    [datetime.date(2005, 2, 14), datetime.date(2005, 3, 14)]
    >>> Entry.objects.dates("pub_date", "day")
    [datetime.date(2005, 2, 20), datetime.date(2005, 3, 20)]
    >>> Entry.objects.dates("pub_date", "day", order="DESC")
    [datetime.date(2005, 3, 20), datetime.date(2005, 2, 20)]
    >>> Entry.objects.filter(headline__contains="Lennon").dates("pub_date", "day")
    [datetime.date(2005, 3, 20)]

#### `datetimes()`

datetimes(field_name, kind, order='ASC', tzinfo=None)

Renvoie un `QuerySet` dont l’évaluation produit une liste d’objets `datetime.datetime` représentant toutes les dates disponibles d’un type particulier dans le contenu `QuerySet`.

`field_name` doit correspondre au nom d’un champ `DateTimeField` de votre modèle.

`kind` doit être soit `"year"`, `"month"`, `"week"`, `"day"`, `"hour"`, `"minute"` ou `"second"`. Chaque objet `datetime.datetime` de la liste de résultats est « tronqué » selon le `type` donné.

`order`, dont la valeur par défaut est `'ASC'`, doit contenir soit `'ASC'` (chronologique), soit `'DESC'` (chronologique inverse). Cela indique comment trier les résultats.

`tzinfo` définit le fuseau horaire dans lequel les dates/heures sont converties avant leur troncature. En effet, un date/heure peut être représentée différemment en fonction du fuseau horaire actif. Ce paramètre doit être un objet `datetime.tzinfo`. S’il vaut `None`, Django utilise le fuseau horaire actuel. Il n’a aucun effet lorsque `USE_TZ` vaut `False`.

Note

Cette fonction effectue la conversion de fuseau horaire directement dans la base de données. En conséquence, la base de données doit être capable d’interpréter la valeur de `tzinfo.tzname(None)`. Cela se traduit dans les exigences suivantes :

- SQLite : aucune exigence. Les conversions sont effectuées en Python.

- PostgreSQL : aucune exigence (voir Fuseaux horaires).

- Oracle : aucune exigence (voir Choix d’un fichier de fuseaux horaires).

- MySQL : chargement des tables de fuseaux horaires avec mysql_tzinfo_to_sql.

#### `none()`

none()

L’appel à `none()` crée un jeu de requête qui ne renvoie jamais aucun objet et qui ne génère pas de requête lorsqu’on accède à ses résultats. Un jeu de requête `qs.none()` est une instance de `EmptyQuerySet`.

Exemples :

    >>> Entry.objects.none()
    <QuerySet []>
    >>> from django.db.models.query import EmptyQuerySet
    >>> isinstance(Entry.objects.none(), EmptyQuerySet)
    True

#### `all()`

all()

Renvoie une copie du `QuerySet` actuel (ou d’une sous-classe `QuerySet`). Cela peut être utile dans les situations où il peut être possible de recevoir soit un gestionnaire de modèle, soit un `QuerySet`, et que les résultats doivent passer encore par d’autres filtres. Après avoir appelé `all()` sur l’un des types d’objet, vous obtenez dans tous les cas un `QuerySet` en retour.

Lorsqu’un résultat `QuerySet` est évalué, il met normalement ses résultats en cache. Si les données dans la base de données peuvent avoir été modifiées depuis l’évaluation d’un `QuerySet`, vous pouvez obtenir des résultats mis à jour de la même requête en appelant `all()` sur un `QuerySet` déjà évalué.

#### `union()`

union(*other_qs, all=False)

Utilise l’opérateur SQL `UNION` pour combiner les résultats de deux `QuerySet` ou plus. Par exemple :

    >>> qs1.union(qs2, qs3)

L’opérateur `UNION` ne sélectionne que les valeurs distinctes par défaut. Pour autoriser des valeurs dupliquées, utilisez le paramètre `all=True`.

`union()`, `intersection()` et `difference()` renvoient des instances de modèles du type du premier jeu de requête, même si les paramètres sont des jeux de requête d’autres modèles. Il est possible de transmettre des modèles différents pour autant que la liste de `SELECT` soit la même pour tous les jeux de requête (au moins les types, les noms n’étant pas un problème si les types correspondent dans le même ordre). Dans de telles situations, vous devez utiliser les noms de colonnes du premier jeu de requête dans les méthodes `QuerySet` appliquées au résultat obtenu. Par exemple :

    >>> qs1 = Author.objects.values_list("name")
    >>> qs2 = Entry.objects.values_list("headline")
    >>> qs1.union(qs2).order_by("name")

De plus, seules les opérations `LIMIT`, `OFFSET`, `COUNT(*)`, `ORDER BY` et les indications de colonnes (c’est-à-dire la segmentation, le compte `count()`, `exists()`, le tri `order_by()` et `values()`/`values_list()`) sont autorisés sur le jeu de requête résultant. D’autre part, les bases de données définissent des restrictions quant aux opérations autorisées dans les requêtes combinées. Par exemple, la plupart des bases de données ne permettent pas les instructions `LIMIT` ou `OFFSET` dans les requêtes combinées.

#### `intersection()`

intersection(*other_qs)

Utilise l’opérateur SQL `INTERSECT` pour renvoyer les éléments communs à deux ou plusieurs `QuerySet`. Par exemple :

    >>> qs1.intersection(qs2, qs3)

Voir `union()` concernant quelques restrictions.

#### `difference()`

difference(*other_qs)

Utilise l’opérateur SQL `EXCEPT` pour ne conserver que les éléments présents dans un `QuerySet` mais pas dans d’autres `QuerySet`. Par exemple :

    >>> qs1.difference(qs2, qs3)

Voir `union()` concernant quelques restrictions.

#### `fetch_mode()`

New in Django 6.1.

fetch_mode(mode)

Returns a `QuerySet` that sets the given fetch mode for all model instances created by this `QuerySet`. The fetch mode controls on-demand loading of fields when they are accessed, such as for foreign keys and deferred fields. For example, to use the `FETCH_PEERS` mode to batch-load all related objects on first access:

    from django.db import models

    books = Book.objects.fetch_mode(models.FETCH_PEERS)

See more in the fetch mode topic guide.

#### `select_related()`

select_related(*fields)

Returns a `QuerySet` that will join in the named foreign-key relationships, selecting additional related objects when it executes its query. This method can be a performance booster, fetching data ahead of time rather than triggering on-demand loading through the model instances” fetch mode, at the cost of a more complex initial query.

Les exemples suivants illustrent la différence entre les requêtes simples et les requêtes `select_related()`. Voici la requête standard :

    # Hits the database.
    e = Entry.objects.get(id=5)

    # Hits the database again to get the related Blog object.
    b = e.blog

Et voici la requête `select_related`:

    # Hits the database.
    e = Entry.objects.select_related("blog").get(id=5)

    # Doesn't hit the database, because e.blog has been prepopulated
    # in the previous query.
    b = e.blog

You can use `select_related()` with any queryset. The order of chaining with other methods isn’t important. For example, these querysets are equivalent:

    Entry.objects.filter(pub_date__gt=timezone.now()).select_related("blog")
    Entry.objects.select_related("blog").filter(pub_date__gt=timezone.now())

Vous pouvez suivre les clés étrangères de la même manière que dans les requêtes. Si vous avez les modèles suivants :

    from django.db import models

    class City(models.Model):
        # ...
        pass

    class Person(models.Model):
        # ...
        hometown = models.ForeignKey(
            City,
            on_delete=models.SET_NULL,
            blank=True,
            null=True,
        )

    class Book(models.Model):
        # ...
        author = models.ForeignKey(Person, on_delete=models.CASCADE)

Alors un appel à `Book.objects.select_related('author__hometown').get(id=4)` mettra en cache l’objet `Person` lié et l’objet `City` lié :

    # Hits the database with joins to the author and hometown tables.
    b = Book.objects.select_related("author__hometown").get(id=4)
    p = b.author  # Doesn't hit the database.
    c = p.hometown  # Doesn't hit the database.

    # Without select_related()...
    b = Book.objects.get(id=4)  # Hits the database.
    p = b.author  # Hits the database.
    c = p.hometown  # Hits the database.

Vous pouvez faire référence à toute relation `ForeignKey` ou `OneToOneField` dans la liste des champs transmis à `select_related()`.

Il est également possible de se référer à la liaison inverse d’un champ `OneToOneField` dans la liste des champs transmis à `select_related` — c’est-à-dire qu’il est possible d’accéder à un champ `OneToOneField` depuis les deux côtés de la relation, et non seulement depuis l’objet dans lequel il est défini. Au lieu d’indiquer le nom du champ, il faut alors utiliser le nom `related_name` du champ à partir de l’objet lié.

Si vous avez besoin d’effacer la liste des champs liés ajoutée par de précédents appels à `select_related` sur un `QuerySet`, vous pouvez passer `None` comme paramètre :

    >>> without_relations = queryset.select_related(None)

L’enchaînement d’appels à `select_related` fonctionne de manière semblable à d’autres méthodes, c’est-à-dire que `select_related('foo', 'bar')` est équivalent à `select_related('foo').select_related('bar')`.

Dans certaines situations, il peut être souhaitable d’appeler `select_related()` avec beaucoup d’objets liés ou avec des relations qu’on ne connaît pas d’avance. Dans ce cas, il est possible d’appeler `select_related()` sans paramètre. Toutes les relations de clé étrangère non nulles seront suivies, mais les clés étrangères pouvant être nulles doivent être indiquées explicitement. Ce n’est pas recommandé dans la plupart des cas car par rapport aux besoins réels, la requête sous-jacente sera certainement plus complexe et les données récupérées plus nombreuses.

Obsolète depuis la version 6.1: Calling `select_related()` with no arguments is deprecated, and support for it will be removed in Django 7.0. Specify the fields to fetch instead.

#### `prefetch_related()`

prefetch_related(*lookups)

Returns a `QuerySet` that will automatically retrieve the given lookups, each in one extra batch query. Prefetching is a way to optimize database access when you know you’ll be accessing related objects later, so you can avoid triggering the on-demand loading behavior of the model instances” fetch mode.

This method has a similar purpose to `select_related()`, in that both are designed to eagerly fetch related objects. However, they work in different ways.

`select_related` fonctionne en créant une jointure SQL et en incluant les champs de l’objet lié dans l’instruction `SELECT`. Pour cette raison, `select_related` récupère les objets liés dans la même requête de base de données. Cependant, pour éviter le jeu de requête bien plus grand qui résulterait de jointures par des liaisons « plusieurs », `select_related` se limite aux relations univaluées, les clés étrangères et les liaisons un-à-un.

`prefetch_related`, de son côté, effectue une requête séparée pour chaque relation et procède à la réconciliation des données dans le code Python. Cela lui permet de précharger les objets plusieurs-à-plusieurs, plusieurs-à-un et `GenericRelation`, ce qui n’est pas possible avec `select_related`, en plus des liaisons de clé étrangère et un-à-un qui sont prises en charge par `select_related`. Il permet également de précharger les liaisons `GenericForeignKey`, cependant, le jeu de requête de chaque type `ContentType` doit être fourni dans le paramètre `querysets` de `GenericPrefetch`.

Par exemple, supposons que vous ayez ces modèles :

    from django.db import models

    class Topping(models.Model):
        name = models.CharField(max_length=30)

    class Pizza(models.Model):
        name = models.CharField(max_length=50)
        toppings = models.ManyToManyField(Topping)

        def __str__(self):
            return "%s (%s)" % (
                self.name,
                ", ".join(topping.name for topping in self.toppings.all()),
            )

et que vous exécutez :

    >>> Pizza.objects.all()
    <QuerySet [<Pizza: Hawaiian (ham, pineapple)>, <Pizza: Seafood (prawns, smoked salmon)>, ...]>

Le problème de ce code est que chaque fois que `Pizza.__str__()` fait appel à `self.toppings.all()`, il doit interroger la base de données, ce qui fait que `Pizza.objects.all()` lance une requête sur la table `Toppings` pour chaque objet du `QuerySet` des pizzas.

Nous pouvons réduire cela à deux seules requêtes en utilisant `prefetch_related`:

    >>> Pizza.objects.prefetch_related("toppings")

Cette syntaxe sous-entend que `self.toppings.all()` est demandé pour chaque `Pizza`; dès cet instant, chaque fois que `self.toppings.all()` est appelé, au lieu de recourir à la base de données pour obtenir les objets, Django les retrouve dans un `QuerySet` préchargé en cache qui a été rempli par une seule requête.

C’est-à-dire que tous les `Toppings` appropriés auront été récupérés par une seule requête et qu’ils auront été utilisés pour créer des instances `QuerySet` dont le cache est prérempli par les résultats appropriés ; ces instances sont ensuite exploitées lors des appels à `self.toppings.all()`.

Les requêtes supplémentaires dans `prefetch_related()` sont exécutées après que le `QuerySet` a commencé à être évalué et que la requête de base a été exécutée.

Notez qu’il n’existe aucun mécanisme pour empêcher une autre requête de base de données de modifier les éléments entre l’exécution de la requête principale et les requêtes supplémentaires, ce qui pourrait conduire à un résultat incohérent. Par exemple, si une `Pizza` est supprimée après que la requête principale a été exécutée, ses garnitures ne seront pas renvoyées dans la requête supplémentaire et il pourrait sembler que la pizza n’a pas de garniture.

    >>> Pizza.objects.prefetch_related("toppings")
    #  "Hawaiian" Pizza was deleted in another shell.
    <QuerySet [<Pizza: Hawaiian ()>, <Pizza: Seafood (prawns, smoked salmon)>]>

Si vous disposez d’une série d’instances de modèles, vous pouvez précharger les attributs liés de ces instances en utilisant la fonction `prefetch_related_objects()`.

Notez que le cache des résultats du `QuerySet` principal et tous les objets liés visés sera alors complètement chargé en mémoire. Cela change du comportement habituel de l’objet `QuerySet` qui essaie autant que possible de ne pas charger tous les objets en mémoire tant qu’ils ne sont pas nécessaires, même après qu’une première requête a été exécutée en base de données.

Note

Rappelez-vous que comme toujours avec les objets `QuerySet`, toute méthode s’enchaînant ultérieurement et impliquant une requête de base de données différente ignore les résultats précédents du cache, et actualise les données par une nouvelle requête en base de données. Ainsi, si vous écrivez ceci :

    >>> pizzas = Pizza.objects.prefetch_related("toppings")
    >>> [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]

…le fait que `pizza.toppings.all()` a été préchargé ne vous aidera pas. `prefetch_related('toppings')` sous-entend `pizza.toppings.all()`, mais `pizza.toppings.filter()` est une nouvelle et différente requête. Le cache préchargé ne vous aide en rien ici. Il s’agit même d’une perte de performances, car vous avez généré une requête de base de données qui ne sera pas utilisée. Ceci montre qu’il faut utiliser cette fonctionnalité avec prudence !

Also, if you call the database-altering methods `add()`, `create()`, `remove()`, `clear()` or `set()`, on a `RelatedManager`, any prefetched cache for the relation will be cleared.

Il est aussi possible d’utiliser la syntaxe de jointure normale pour se référer à des champs liés de champs liés. Supposons qu’un modèle supplémentaire est ajouté à l’exemple précédent :

    class Restaurant(models.Model):
        pizzas = models.ManyToManyField(Pizza, related_name="restaurants")
        best_pizza = models.ForeignKey(
            Pizza, related_name="championed_by", on_delete=models.CASCADE
        )

Toutes les expressions suivantes sont admises :

    >>> Restaurant.objects.prefetch_related("pizzas__toppings")

Cela va précharger toutes les pizzas appartenant aux restaurants ainsi que toutes les garnitures (`toppings`) de ces pizzas. Au total, 3 requêtes de base de données seront générées : une pour les restaurants, une pour les pizzas et une pour les garnitures.

    >>> Restaurant.objects.prefetch_related("best_pizza__toppings")

Cette requête récupère la meilleure pizza et toutes les garnitures de la meilleure pizza de chaque restaurant. Cela se fera en 3 requêtes de base de données, une pour les restaurants, une pour les « meilleures pizzas » et une pour les garnitures.

La relation `best_pizza` pourrait aussi être récupérée par `select_related` pour réduire le nombre de requêtes à 2 :

    >>> Restaurant.objects.select_related("best_pizza").prefetch_related("best_pizza__toppings")

Comme le préchargement a lieu après la requête principale (qui inclut les jointures requises par `select_related`), il est capable de détecter que les objets `best_pizza` ont déjà été récupérés, et il évitera de les récupérer une fois de plus.

L’enchaînement d’appels à `prefetch_related` accumule les liaisons à précharger. Pour effacer tout comportement lié à `prefetch_related`, passez `None` en paramètre :

    >>> non_prefetched = qs.prefetch_related(None)

Une différence à signaler lors de l’utilisation de `prefetch_related` est que les objets créés par une requête peuvent être partagés entre les différents objets auxquels ils sont liés, c’est-à-dire qu’une même instance de modèle Python peut apparaître à plus d’un endroit dans l’arborescence des objets renvoyés. Cela se produit normalement avec les relations de clé étrangère. Ce comportement ne pose généralement pas de problème et permet d’économiser à la fois de la mémoire et du temps processeur.

Même si `prefetch_related` prend en charge le préchargement des relations `GenericForeignKey`, le nombre de requêtes dépend des données. Comme un champ `GenericForeignKey` peut référencer des données de tables différentes, il sera nécessaire d’effectuer une requête par table référencée, au lieu d’une seule requête pour tous les éléments. Il pourrait aussi y avoir des requêtes supplémentaires pour la table `ContentType` si les lignes concernées n’ont pas déjà été obtenues.

Dans la plupart des cas, `prefetch_related` est implémenté par une requête SQL utilisant l’opérateur « IN ». Cela implique que pour un grand `QuerySet`, cela peut générer une grande clause « IN », ce qui, en fonction de la base de données, peut poser en soi des problèmes de performance au moment d’analyser ou d’exécuter la requête SQL. Évaluez toujours les performances en fonction de votre cas d’utilisation !

Si vous utilisez `iterator()` pour exécuter la requête, les appels à `prefetch_related()` ne seront respectés que si une valeur est fournie pour `chunk_size`.

Vous pouvez utiliser l’objet `Prefetch` pour contrôler de manière plus fine l’opération de préchargement.

Dans sa forme la plus simple, `Prefetch` est équivalent aux recherches traditionnelles basées sur les chaînes :

    >>> from django.db.models import Prefetch
    >>> Restaurant.objects.prefetch_related(Prefetch("pizzas__toppings"))

Vous pouvez préciser un jeu de requête personnalisé par le paramètre facultatif `queryset`. Cela peut par exemple être utilisé pour modifier l’ordre de tri par défaut du jeu de requête :

    >>> Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas__toppings", queryset=Toppings.objects.order_by("name"))
    ... )

Ou pour appeler `select_related()` lorsque c’est nécessaire afin de réduire encore plus le nombre de requêtes :

    >>> Pizza.objects.prefetch_related(
    ...     Prefetch("restaurants", queryset=Restaurant.objects.select_related("best_pizza"))
    ... )

Vous pouvez aussi attribuer le résultat du préchargement à un attribut personnalisé au moyen du paramètre facultatif `to_attr`. Le résultat sera directement stocké dans une liste.

Cela permet de précharger plusieurs fois la même relation avec un `QuerySet` différent ; par exemple :

    >>> vegetarian_pizzas = Pizza.objects.filter(vegetarian=True)
    >>> Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas", to_attr="menu"),
    ...     Prefetch("pizzas", queryset=vegetarian_pizzas, to_attr="vegetarian_menu"),
    ... )

Les recherches créées avec un paramètre `to_attr` personnalisé peuvent toujours être traversées comme de coutume par d’autres recherches :

    >>> vegetarian_pizzas = Pizza.objects.filter(vegetarian=True)
    >>> Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas", queryset=vegetarian_pizzas, to_attr="vegetarian_menu"),
    ...     "vegetarian_menu__toppings",
    ... )

L’utilisation de `to_attr` est recommandée lors d’un filtrage restrictif du résultat préchargé car c’est moins ambigu que de stocker un résultat filtré dans le cache du gestionnaire de liaison :

    >>> queryset = Pizza.objects.filter(vegetarian=True)
    >>>
    >>> # Recommended:
    >>> restaurants = Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas", queryset=queryset, to_attr="vegetarian_pizzas")
    ... )
    >>> vegetarian_pizzas = restaurants[0].vegetarian_pizzas
    >>>
    >>> # Not recommended:
    >>> restaurants = Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas", queryset=queryset),
    ... )
    >>> vegetarian_pizzas = restaurants[0].pizzas.all()

Le préchargement personnalisé fonctionne aussi avec des liaisons avant simples telles que des relations `ForeignKey` ou `OneToOneField`. Généralement, il faut plutôt utiliser `select_related()` pour de telles relations, mais il existe certaines situations où le préchargement avec un jeu `QuerySet` personnalisé est utile :

- Vous souhaitez utiliser un `QuerySet` qui effectue lui aussi un préchargement sur des modèles liés.

- Vous souhaitez précharger uniquement un sous-ensemble d’objets liés.

- You want to use performance optimization techniques like deferring fields, for example, via `defer()` or `only()`:

      >>> queryset = Pizza.objects.only("name")
      >>>
      >>> restaurants = Restaurant.objects.prefetch_related(
      ...     Prefetch("best_pizza", queryset=queryset)
      ... )

Lors de l’utilisation de plusieurs bases de données, `Prefetch` respecte votre choix de base de données. Si la requête interne ne suggère pas de base de données, ce sera la base de données choisie pour la requête externe qui sera utilisée. Toutes les expressions suivantes sont valables :

    >>> # Both inner and outer queries will use the 'replica' database
    >>> Restaurant.objects.prefetch_related("pizzas__toppings").using("replica")
    >>> Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas__toppings"),
    ... ).using("replica")
    >>>
    >>> # Inner will use the 'replica' database; outer will use 'default' database
    >>> Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas__toppings", queryset=Toppings.objects.using("replica")),
    ... )
    >>>
    >>> # Inner will use 'replica' database; outer will use 'cold-storage' database
    >>> Restaurant.objects.prefetch_related(
    ...     Prefetch("pizzas__toppings", queryset=Toppings.objects.using("replica")),
    ... ).using("cold-storage")

Note

L’ordre des recherches a son importance.

Prenez les exemples suivants :

    >>> prefetch_related("pizzas__toppings", "pizzas")

Cela fonctionne même si les paramètres sont dans le désordre, parce que `'pizzas__toppings'` contient déjà toutes les informations nécessaires, et le second paramètre `'pizzas'` est donc redondant.

    >>> prefetch_related("pizzas__toppings", Prefetch("pizzas", queryset=Pizza.objects.all()))

Cette ligne génère une exception `ValueError` en raison de la tentative de redéfinition du jeu de requête d’une recherche précédente. Notez qu’un jeu de requête implicite a été créé pour traverser `'pizzas'` dans le cadre de la recherche `'pizzas__toppings'`.

    >>> prefetch_related("pizza_list__toppings", Prefetch("pizzas", to_attr="pizza_list"))

Cette ligne génère une exception `AttributeError` car `'pizza_list'` n’existe pas encore au moment où `'pizza_list__toppings'` est traité.

Ces considérations ne sont pas limitées à l’utilisation des objets `Prefetch`. Certaines techniques avancées peuvent nécessiter que les recherches soient effectuées dans un ordre précis pour éviter de créer des requêtes supplémentaires ; il est donc recommandé de toujours positionner soigneusement les paramètres de `prefetch_related`.

#### `extra()`

extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)

Il peut arriver parfois que la syntaxe de requête de Django ne puisse pas exprimer facilement une clause `WHERE` complexe. Pour ces cas extrêmes, Django fournit le modificateur de `QuerySet` `extra()`, un point d’entrée pour injecter des clauses spécifiques dans le code SQL généré par un `QuerySet`.

N’utilisez cette méthode qu’en dernier recours

Il s’agit d’une ancienne API que nous prévoyons de rendre obsolète à un moment donné. Ne l’utilisez que si vous ne pouvez pas exprimer votre requête en employant d’autres méthodes de jeux de requêtes. Si vous êtes contraint de l’utiliser, créez un ticket en indiquant le mot-clé QuerySet.extra et en présentant votre cas d’utilisation (sans oublier de vérifier d’abord d’éventuels tickets existants) afin que nous puissions améliorer l’API QuerySet pour finalement supprimer `extra()`. Nous n’améliorons ni ne corrigeons plus de bogues pour cette dernière méthode.

Par exemple, cette utilisation de `extra()`:

    >>> qs.extra(
    ...     select={"val": "select col from sometable where othercol = %s"},
    ...     select_params=(someparam,),
    ... )

est équivalent à :

    >>> qs.annotate(val=RawSQL("select col from sometable where othercol = %s", (someparam,)))

Le principal avantage d’utiliser `RawSQL` est qu’il est possible de définir `output_field` si nécessaire. Le désavantage principal est que si vous faites référence à un alias de table du jeu de requête dans le code SQL brut, il est alors possible que Django modifie cet alias (par exemple lorsque le jeu de requête est utilisé comme sous-requête dans une autre requête).

Avertissement

Vous devez être très prudent lors de l’utilisation de `extra()`. Lors de chaque utilisation, vous devez échapper tout paramètre pouvant être contrôlé par les utilisateurs en employant `params` afin de vous protéger contre les attaques par injection SQL.

Vous devez aussi éviter de placer les substituants entre guillemets dans la chaîne SQL. Cet exemple est vulnérable à l’injection SQL en raison des guillemets autour de `%s`:

    SELECT col FROM sometable WHERE othercol = '%s'  # unsafe!

Vous pouvez en apprendre davantage sur le fonctionnement de la protection contre les injections SQL de Django.

Par définition, ces expressions `extra` ne sont pas toujours portables entre moteurs de base de données (parce que vous écrivez du code SQL explicitement) et elles violent le principe DRY (ne pas se répéter), il s’agit donc de les éviter autant que possible.

Indiquez un ou plusieurs des paramètres `params`, `select`, `where` ou `tables`. Aucun n’est obligatoire, mais vous devez en indiquer au moins un.

- `select`

  Le paramètre `select` vous permet d’indiquer des champs supplémentaires dans la clause `SELECT`. Ce doit être un dictionnaire faisant correspondre des noms d’attributs à des clauses SQL utilisées pour calculer l’attribut concerné.

  Exemple :

      Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"})

  Avec ceci, chaque objet `Entry` possède un attribut supplémentaire, `is_recent`, une valeur booléenne indiquant si le champ `pub_date` de l’objet est plus grand que le 1er janvier 2006.

  Django insère l’extrait SQL donné directement dans l’instruction `SELECT`. Le code SQL résultant de l’exemple ci-dessus ressemblerait donc à ceci :

      SELECT blog_entry.*, (pub_date > '2006-01-01') AS is_recent
      FROM blog_entry;

  L’exemple suivant est plus pointu ; il effectue une sous-requête pour donner à chaque objet `Blog` du résultat un attribut `entry_count`, un nombre entier comptant les objets `Entry` associés :

      Blog.objects.extra(
          select={
              "entry_count": "SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id"
          },
      )

  Dans ce cas particulier, nous exploitons le fait que la requête contiendra déjà la table `blog_blog` dans sa clause `FROM`.

  Le code SQL résultant de l’exemple ci-dessus donnerait :

      SELECT blog_blog.*, (SELECT COUNT(*) FROM blog_entry WHERE blog_entry.blog_id = blog_blog.id) AS entry_count
      FROM blog_blog;

  Notez que les parenthèses exigées par la plupart des moteurs de base de données autour des sous-requêtes ne sont pas obligatoires dans les clauses `select` de Django.

  Dans certains cas exceptionnels, il peut être souhaitable de transmettre des paramètres aux fragments SQL dans `extra(select=...)`. Pour faire cela, utilisez le paramètre `select_params`.

  Ceci fonctionnera, par exemple :

      Blog.objects.extra(
          select={"a": "%s", "b": "%s"},
          select_params=("one", "two"),
      )

  Si vous avez besoin d’utiliser un `%s` littéral à l’intérieur de la chaîne de sélection, utilisez la séquence `%%s`.

- `where` / `tables`

  Il est possible de définir des clauses SQL `WHERE` explicites — peut-être pour effectuer des jointures non explicites — en utilisant `where`. Des tables peuvent être manuellement ajoutées à la clause SQL `FROM` par le paramètre `tables`.

  `where` et `tables` acceptent tous deux une liste de chaînes de caractères. Tous les paramètres `where` sont combinés avec les autres critères de recherche par l’opérateur « ET ».

  Exemple :

      Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])

  …peut être (grossièrement) traduit en code SQL comme :

      SELECT * FROM blog_entry WHERE (foo='a' OR bar='a') AND (baz='a')

  Soyez prudent en utilisant le paramètre `tables` si celui-ci contient des tables déjà utilisées dans le requête. Lorsque vous ajoutez des tables supplémentaires par le paramètre `tables`, Django suppose que vous voulez que cette table soit ajoutée une fois de plus, si elle s’y trouve déjà. Cela pose un problème, car le nom de table recevra alors un alias. Si une table apparaît plusieurs fois dans une instruction SQL, son nom est remplacé par un alias à partir de la deuxième occurrence, afin que la base de données puisse les différencier. Si alors dans le paramètre `where` supplémentaire, vous vous référez à la table que vous avez explicitement ajoutée, vous obtiendrez des erreurs.

  En temps normal, seules les tables qui ne font pas encore partie de la requête devraient être ajoutées. Cependant, si le cas ci-dessus se présente, il existe des solutions. Regardez premièrement si vous pouvez éviter d’inclure la table supplémentaire et utiliser celle qui se trouve déjà dans la requête. Si ce n’est pas possible, placez l’appel `extra()` au début de la construction du jeu de requête afin que la table concernée soit la première occurrence. Finalement, si aucune autre solution ne fonctionne, examinez la requête générée et réécrivez le contenu `where` afin d’utiliser l’alias attribué à la table supplémentaire. L’alias sera toujours le même tant que vous construisez le jeu de requête de la même manière, il est donc possible de se fier à la stabilité du nom d’alias.

- `order_by`

  Si vous avez besoin de trier les résultats de requête à l’aide de nouveaux champs ou tables que vous avez inclus par `extra()`, utilisez le paramètre `order_by` de `extra()` et complétez-le par une liste de chaînes. Celles-ci doivent correspondre soit à des champs de modèles (comme pour la méthode `order_by()` habituelle des jeux de requête) sous la forme `nom_table.nom_colonne`, soit à un alias d’une colonne définie dans le paramètre `select` de `extra()`.

  Par exemple :

      q = Entry.objects.extra(select={"is_recent": "pub_date > '2006-01-01'"})
      q = q.extra(order_by=["-is_recent"])

  Ce code place en premier dans les résultats tous les éléments pour lesquels `is_recent` vaut `True` (dans un tri descendant, `True` apparaît avant `False`).

  Par ailleurs, cela montre aussi que vous pouvez appelez `extra()` plusieurs fois en obtenant le comportement attendu (ajout successif de nouvelles contraintes).

- `params`

  Le paramètre `where` décrit ci-dessus peut utiliser des chaînes de substitution de base de données comme en Python standard, `'%s'`, pour indiquer au moteur de base de données des paramètres qu’il faut automatiquement placer entre guillemets. Le paramètre `params` est une liste de paramètres supplémentaires à utiliser dans la substitution.

  Exemple :

      Entry.objects.extra(where=["headline=%s"], params=["Lennon"])

  Utilisez toujours `params` au lieu d’insérer des valeurs directement dans la clause `where`, parce que `params` garantit que les valeurs seront mises correctement entre guillemets en fonction de la base de données utilisée. Par exemple, les guillemets dans les chaînes seront échappés correctement.

  Faux :

      Entry.objects.extra(where=["headline='Lennon'"])

  Juste :

      Entry.objects.extra(where=["headline=%s"], params=["Lennon"])

Avertissement

Si vous effectuez des requêtes vers MySQL, notez que le forçage de type silencieux de MySQL peut produire des résultats inattendus lors du mélange de types. Si une requête porte sur une colonne de type chaîne mais contient une valeur nombre entier, MySQL transforme le type de toutes les valeurs de la table en nombre entier avant d’effectuer la comparaison. Par exemple, si la table contient les valeurs `'abc'`, `'def'` et que la requête contient `WHERE macolonne=0`, les deux lignes seront sélectionnées. Pour empêcher cela, effectuez les transformations de type avant d’utiliser une valeur dans une requête.

#### `defer()`

defer(*fields)

Dans certaines situations complexes de structures de données, des modèles peuvent contenir un grand nombre de champs, et certains champs contenir beaucoup de données (par exemple pour les champs texte) ; parfois, la conversion de certaines valeurs en objet Python est coûteuse en performances. Si vous utilisez les résultats d’une requête dans une situation où vous n’êtes pas certain d’avoir besoin de certains champs lors de la requête initiale pour obtenir les données, vous pouvez indiquer à Django de ne pas les récupérer de la base de données.

Ceci se fait en indiquant les noms des champs à ne pas charger dans `defer()`:

    Entry.objects.defer("headline", "body")

Un jeu de requête comportant des champs différés renvoie tout de même des instances de modèles. Chaque champ différé sera récupéré de la base de données si vous y faites référence (un à la fois, pas tous les champs différés d’un coup).

Note

Les champs différés ne seront pas différés ainsi à partir du code asynchrone. Vous obtiendrez au lieu de cela une exception `SynchronousOnlyOperation`. SI vous écrivez du code asynchrone, vous ne devez pas essayer d’accéder aux champs ciblés par `defer()`.

On peut appeler plusieurs fois `defer()`. Chaque appel ajoute les nouveaux champs à l’ensemble des champs différés :

    # Defers both the body and headline fields.
    Entry.objects.defer("body").filter(rating=5).defer("headline")

L’ordre dans lequel les champs sont ajoutés à l’ensemble différé n’a pas d’importance. L’appel à `defer()` avec un nom de champ qui a déjà été indiqué comme différé ne pose pas de problème (le champ sera toujours considéré comme différé).

Vous pouvez différer le chargement de champs dans des modèles liés (si les modèles liés sont chargés par `select_related()`) en utilisant la notation standard de double soulignement pour séparer les champs liés :

    Blog.objects.select_related().defer("entry__headline", "entry__body")

Si vous souhaitez effacer l’ensemble des champs différés, indiquez `None` comme paramètre à `defer()`:

    # Load all fields immediately.
    my_queryset.defer(None)

Certains champs d’un modèle ne seront pas différés, même si vous demandez de le faire. Le chargement de la clé primaire ne peut jamais être différé. Si vous utilisez `select_related()` pour récupérer des modèles liés, vous ne devriez pas différer le chargement du champ qui fait la liaison entre le modèle principal et le modèle lié, sous peine d’obtenir une erreur.

De même, l’appel à `defer()` (ou à sa contrepartie `only()`) incluant un argument provenant d’une agrégation (par ex. un résultat de `annotate()`) ne fait pas de sens : une exception sera alors produite. Les valeurs agrégées seront toujours récupérées dans le jeu de requête résultant.

Note

La méthode `defer()` (et sa cousine `only()` décrite ci-dessous) est réservée aux situations spéciales. Elles permettent d’optimiser après avoir analysé attentivement les requêtes en comprenant exactement les informations nécessaires et après avoir mesuré que la différence entre le chargement des champs utiles ou le chargement de tous les champs du modèle constitue une amélioration significative.

Even if you think you are in the advanced use-case situation, only use `defer()` when you cannot, at queryset load time, determine if you will need the extra fields or not. If you are frequently loading and using a particular subset of your data, the best choice you can make is to normalize your models and put the non-loaded data into a separate model (and database table). If the columns must stay in the one table for some reason, create a model with `Meta.managed = False` (see the `managed` documentation) containing just the fields you normally need to load and use that where you might otherwise call `defer()`. This makes your code more explicit to the reader, is slightly faster and consumes a little less memory in the Python process.

Par exemple, ces modèles utilisent tous deux la même table de base de données en arrière-plan :

    class CommonlyUsedModel(models.Model):
        f1 = models.CharField(max_length=10)

        class Meta:
            managed = False
            db_table = "app_largetable"

    class ManagedModel(models.Model):
        f1 = models.CharField(max_length=10)
        f2 = models.CharField(max_length=10)

        class Meta:
            db_table = "app_largetable"

    # Two equivalent QuerySets:
    CommonlyUsedModel.objects.all()
    ManagedModel.objects.defer("f2")

Si plusieurs champs ont besoin d’être dupliqués dans le modèle non piloté, il peut être préférable de créer un modèle abstrait avec les champs partagés et de faire ensuite hériter les modèles piloté et non piloté de ce modèle abstrait.

Note

Lors de l’appel à `save()` pour des instances avec champs différés, seuls les champs chargés sont enregistrés. Voir `save()` pour plus de détails.

#### `only()`

only(*fields)

La méthode `only()` est essentiellement l’inverse de `defer()`. Seuls les champs passés à cette méthode et qui ne sont pas encore marqués comme différés sont immédiatement chargés lors de l’évaluation de la requête.

Si vous avez un modèle dont presque tous les champs ont besoin d’être différés, l’utilisation de `only()` pour indiquer l’ensemble complémentaire des champs peut aboutir à du code plus simple.

Supposons qu’un modèle possède les champs `name`, `age` et `biography`. Les deux requêtes suivantes sont identiques en terme de champs différés :

    Person.objects.defer("age", "biography")
    Person.objects.only("name")

À chaque appel de `only()`, l’ensemble des champs à charger immédiatement est remplacé. Le nom de la méthode est mnémonique : seuls (only en anglais) ces champs sont chargés immédiatement ; les autres sont différés. Ainsi, quand `only()` est appelé plusieurs fois successivement, seuls les champs du dernier appel sont pris en compte :

    # This will defer all fields except the headline.
    Entry.objects.only("body", "rating").only("headline")

Comme `defer()` se comporte de manière incrémentale (ajoutant les champs à la liste différée), vous pouvez combiner les appels à `only()` et `defer()` et tout devrait se passer comme prévu :

    # Final result is that everything except "headline" is deferred.
    Entry.objects.only("headline", "body").defer("body")

    # Final result loads headline immediately.
    Entry.objects.defer("body").only("headline", "body")

Tous les avertissements de la note de la documentation de `defer()` s’appliquent également à `only()`. Utilisez-la prudemment et seulement après avoir épuisé les autres options possibles.

Utiliser `only()` en omettant un champ demandé dans `select_related()` est aussi une erreur. D’un autre côté, appeler `only()` sans argument va renvoyer tous les champs (y compris les annotations) récupérés par le jeu de requête.

Comme pour `defer()`, vous ne pouvez pas accéder aux champs non chargés à partir de code asynchrone et vous attendre à ce qu’ils soient chargés. Vous obtiendrez plutôt une exception `SynchronousOnlyOperation`. Assurez-vous que tous les champs auxquels vous pourriez accéder soient compris dans votre appel à `only()`.

Note

Lors de l’appel à `save()` pour des instances avec champs différés, seuls les champs chargés sont enregistrés. Voir `save()` pour plus de détails.

Note

Lors de l’utilisation de meth:defer après `only()`, les champs dans `defer()` seront prioritaires par rapport aux champs de `only()` pour les champs mentionnés dans les deux appels.

#### `using()`

using(alias)

Cette méthode sert à contrôler la base de données qui sera la cible d’évaluation du `QuerySet` dans le cas où plusieurs bases de données sont définies. Le seul paramètre admis par cette méthode est l’alias d’une base de données, tel que défini dans `DATABASES`.

Par exemple :

    # queries the database with the 'default' alias.
    >>> Entry.objects.all()

    # queries the database with the 'backup' alias
    >>> Entry.objects.using("backup")

#### `select_for_update()`

select_for_update(nowait=False, skip_locked=False, of=(), no_key=False)

Renvoie un jeu de requête qui verrouille les lignes jusqu’à la fin de la transaction, générant une instruction SQL `SELECT ... FOR UPDATE` pour les bases de données qui la prennent en charge.

Par exemple :

    from django.db import transaction

    entries = Entry.objects.select_for_update().filter(author=request.user)
    with transaction.atomic():
        for entry in entries:
            ...

Lorsque le jeu de requête est évalué (`for entry in entries` dans ce cas), toutes les lignes de base de données correspondantes sont verrouillées jusqu’à la fin du bloc transactionnel, ce qui veut dire que d’autres transactions ne pourront ni modifier ni verrouiller elles-mêmes ces lignes.

Normalement, si une autre transaction a déjà verrouillé l’une des lignes sélectionnées, la requête est bloquée en attendant que le verrou soit levé. Si ce n’est pas ce que vous voulez, appelez `select_for_update(nowait=True)`. L’appel est alors non bloquant. Si un verrou est déjà posé par une autre transaction sur un des éléments à sélectionner, une exception `DatabaseError` est générée lors de l’évaluation du jeu de requête. Il est aussi possible d’ignorer les lignes verrouillées en utilisant plutôt `select_for_update(skip_locked=True)`. Les paramètres `nowait` et `skip_locked` sont mutuellement exclusifs ; s’ils sont les deux activés lors de l’appel à `select_for_update()`, une erreur `ValueError` sera produite.

Par défaut, `select_for_update()` verrouille toutes les lignes qui sont sélectionnées par la requête. Par exemple, les lignes des objets liés mentionnés dans `select_related()` sont verrouillés en plus des lignes du modèle du jeu de requête. Si ce n’est pas souhaité, indiquez les objets liés que vous voulez verrouiller dans `select_for_update(of=(...))` en utilisant la même syntaxe de noms de champs que pour `select_related()`. Utilisez la valeur `'self'` pour vous référer au modèle du jeu de requête.

Verrouille les modèles parents dans `select_for_update(of=(...))`

Si vous souhaitez verrouiller les modèles parents dans un contexte d’héritage multiple, vous devez indiquer les champs de lien parent (par défaut `<parent_model_name>_ptr`) dans le paramètre `of`. Par exemple

    Restaurant.objects.select_for_update(of=("self", "place_ptr"))

Utilisation de `select_for_update(of=(...))` avec des champs précis

Si vous souhaitez verrouiller des modèles et indiquer des champs sélectionnés, par ex. en utilisant `values()`, vous devez choisir au moins un champ de chaque modèle dans l’argument `of`. Les modèles sans champ sélectionné ne seront pas verrouillés.

Avec PostgreSQL uniquement, vous pouvez passer `no_key=True` afin d’acquérir un verrou plus faible, qui permet quand même la création de lignes qui ne font que référencer les lignes verrouillées (au travers d’une clé étrangère, par exemple). La documentation PostgreSQL contient plus de détails au sujet des modes de verrouillage au niveau ligne.

Il n’est pas possible d’utiliser `select_for_update()` sur des relations pouvant être nulles :

    >>> Person.objects.select_related("hometown").select_for_update()
    Traceback (most recent call last):
    ...
    django.db.utils.NotSupportedError: FOR UPDATE cannot be applied to the nullable side of an outer join

Pour éviter cette restriction, vous pouvez exclure les objets nuls si vous n’en avez pas besoin :

    >>> Person.objects.select_related("hometown").select_for_update().exclude(hometown=None)
    <QuerySet [<Person: ...>, ...]>

The `postgresql`, `oracle`, and `mysql` database backends support `select_for_update()`. However, MariaDB only supports the `nowait` and `skip_locked` arguments, and MySQL supports the `nowait`, `skip_locked`, and `of` arguments. The `no_key` argument is only supported on PostgreSQL.

Si vous passez `nowait=True`, `skip_locked=True`, `no_key=True` ou `of` à `select_for_update()` et que le moteur de base de données ne prend pas en charge ces options, comme pour MySQL, une exception `NotSupportedError` est générée. Ceci évite que du code soit bloqué de manière inattendue.

L’évaluation d’un jeu de requête avec `select_for_update()` en mode autocommit avec les bases de données qui prennent en charge `SELECT ... FOR UPDATE` est une erreur `TransactionManagementError`, car dans ce cas-là, les lignes ne sont pas verrouillées. Si c’était permis, ce serait un vecteur de corruption de données qui pourrait facilement être provoqué par l’appel de code conçu pour être exécuté dans une transaction en dehors d’une transaction.

L’emploi de `select_for_update()` avec des moteurs qui ne prennent pas en charge `SELECT ... FOR UPDATE` (comme pour SQLite) n’aura aucun effet. `SELECT ... FOR UPDATE` ne sera pas ajouté à la requête et aucune erreur ne sera produite si `select_for_update()` est utilisé en mode autocommit.

Avertissement

Même si `select_for_update()` échoue normalement en mode autocommit, puisque `TestCase` englobe automatiquement chaque test dans une transaction, l’appel à `select_for_update()` dans un `TestCase` même en dehors d’un bloc `atomic()` va passer (peut-être de façon inattendue) sans générer d’exception `TransactionManagementError`. Pour tester convenablement `select_for_update()`, vous devez utiliser `TransactionTestCase`.

Certaines expressions peuvent ne pas être prises en charge

PostgreSQL ne prend pas en charge `select_for_update()` avec les expressions `Window`.

#### `raw()`

raw(raw_query, params=(), translations=None, using=None)

Accepte une requête SQL brute, l’exécute et renvoie une instance `django.db.models.query.RawQuerySet`. Il est possible alors d’effectuer une boucle sur cette instance `RawQuerySet` tout comme pour un objet `QuerySet` normal afin d’accéder aux instances d’objets.

Voir Lancement de requêtes SQL brutes pour plus d’informations.

Avertissement

`raw()` génère toujours une nouvelle requête et ne tient pas compte d’éventuels filtrages précédents. Ainsi, elle ne devrait généralement être appelée que depuis un `Manager` ou une instance `QuerySet` toute neuve.

### Opérateurs renvoyant de nouveaux `QuerySet`

Les jeux de requête combinés doivent utiliser le même modèle.

#### AND (`&`)

Combine deux objets `QuerySet` en utilisant l’opérateur SQL `AND` d’une manière semblable au chaînage des filtres.

Les requêtes suivantes sont équivalentes

    Model.objects.filter(x=1) & Model.objects.filter(y=2)
    Model.objects.filter(x=1).filter(y=2)

Équivalent SQL :

    SELECT ... WHERE x=1 AND y=2

#### OR (`|`)

Combine deux requêtes `QuerySet` en utilisant l’opérateur SQL `OR` (OU).

Les requêtes suivantes sont équivalentes

    Model.objects.filter(x=1) | Model.objects.filter(y=2)
    from django.db.models import Q

    Model.objects.filter(Q(x=1) | Q(y=2))

Équivalent SQL :

    SELECT ... WHERE x=1 OR y=2

`|` n’est pas une opération commutative, dans la mesure où des requêtes apparemment équivalentes peuvent aboutir à des requêtes différentes.

#### XOR (`^`)

Combine deux objets `QuerySet` en utilisant l’opérateur SQL `XOR` (ou exclusif). Une expression `XOR` renvoie les lignes qui correspondent à un nombre impair d’opérandes.

Les requêtes suivantes sont équivalentes

    Model.objects.filter(x=1) ^ Model.objects.filter(y=2)
    from django.db.models import Q

    Model.objects.filter(Q(x=1) ^ Q(y=2))

Équivalent SQL :

    SELECT ... WHERE x=1 XOR y=2

Note

`XOR` est pris en charge nativement avec MariaDB et MySQL. Avec les autres bases de données, `x ^ y ^ ... ^ z` est converti en un équivalent :

    (x OR y OR ... OR z) AND
    1=MOD(
        (CASE WHEN x THEN 1 ELSE 0 END) +
        (CASE WHEN y THEN 1 ELSE 0 END) +
        ...
        (CASE WHEN z THEN 1 ELSE 0 END),
        2
    )

### Méthodes qui ne renvoient pas de `QuerySet`

Les méthodes de `QuerySet` suivantes évaluent le `QuerySet` et renvoie quelque chose d’autre qu’un `QuerySet`.

Ces méthodes n’utilisent pas de cache (voir Mise en cache et objets QuerySet). Elles accèdent à la base de données lors de chaque appel.

Comme ces méthodes évaluent l’objet QuerySet, ce sont des appels bloquants et donc leur version principale (synchrone) ne peut pas être appelée à partir de code asynchrone. Pour cette raison, chacune dispose de sa version équivalente asynchrone avec un préfixe `a`. Par exemple, plutôt que `get(…)`, vous pouvez écrire `await aget(…)`.

Il n’y a normalement aucune différence de comportement à part leur nature asynchrone, mais s’il y en a, elles sont décrites dans chaque description de méthode ci-dessous.

#### `get()`

get(*args, **kwargs)

aget(*args, **kwargs)

Version asynchrone: `aget()`

Renvoie l’objet correspondant aux paramètres de recherche indiqués, qui doivent être dans le format décrit dans Recherches dans les champs. Vous devriez utiliser des critères qui sont garantis comme uniques, tels que des clés primaires ou des champs disposant d’une contrainte d’unicité. Par exemple

    Entry.objects.get(id=1)
    Entry.objects.get(Q(blog=blog) & Q(entry_number=1))

Si vous pensez qu’une requête ne contient déjà qu’une seule ligne, vous pouvez utiliser `get()` sans paramètre pour obtenir l’objet correspondant à cette ligne :

    Entry.objects.filter(pk=1).get()

Si `get()` ne trouve aucun objet, il génère l’exception `Model.DoesNotExist`:

    Entry.objects.get(id=-999)  # raises Entry.DoesNotExist

Si `get()` trouve plus qu’un objet, il génère une exception `Model.MultipleObjectsReturned`:

    Entry.objects.get(name="A Duplicated Name")  # raises Entry.MultipleObjectsReturned

Ces deux classes d’exceptions sont des attributs de la classe de modèle et sont spécifiques à ces modèles. Si vous souhaitez intercepter de telles exceptions provenant de plusieurs appels `get()` pour différents modèles, vous pouvez utiliser leur classe de base générique. Par exemple, vous pouvez utiliser `django.core.exceptions.ObjectDoesNotExist` pour intercepter les exceptions `DoesNotExist` de modèles différents

    from django.core.exceptions import ObjectDoesNotExist

    try:
        blog = Blog.objects.get(id=1)
        entry = Entry.objects.get(blog=blog, entry_number=1)
    except ObjectDoesNotExist:
        print("Either the blog or entry doesn't exist.")

#### `create()`

create(**kwargs)

acreate(**kwargs)

Version asynchrone: `acreate()`

Une méthode d’agrément pour la création d’un objet et son enregistrement en une seule méthode. Ainsi :

    p = Person.objects.create(first_name="Bruce", last_name="Springsteen")

et :

    p = Person(first_name="Bruce", last_name="Springsteen")
    p.save(force_insert=True)

sont équivalents.

Le paramètre force_insert est documenté ailleurs, mais il indique qu’un nouvel objet sera toujours créé. Vous n’avez normalement pas à vous préoccuper de ce paramètre. Cependant, si le modèle contient une valeur de clé primaire que vous avez définie manuellement et que cette valeur existe déjà en base de données, l’appel à `create()` échoue avec l’erreur `IntegrityError` car les clés primaires doivent rester uniques. Soyez prêt à traiter l’exception si vous définissez manuellement des clés primaires.

#### `get_or_create()`

get_or_create(defaults=None, **kwargs)

aget_or_create(defaults=None, **kwargs)

Version asynchrone: `aget_or_create()`

Une méthode utile pour rechercher un objet correspondant aux paramètres `kwargs` indiqués (qui peuvent être vides si le modèle contient des valeurs par défaut pour tous les champs), et qui crée un objet si nécessaire.

Renvoie un tuple `(objet, créé)` où `objet` est l’objet chargé ou créé et `créé` est une valeur booléenne indiquant si un nouvel objet a été créé.

L’idée est d’éviter la création d’objets dupliqués lorsque des requêtes sont exécutées en parallèle ; ceci est une sorte de raccourci pour éviter des lignes de code redondantes. Par exemple :

    try:
        obj = Person.objects.get(first_name="John", last_name="Lennon")
    except Person.DoesNotExist:
        obj = Person(first_name="John", last_name="Lennon", birthday=date(1940, 10, 9))
        obj.save()

Ici, il est possible que plusieurs requêtes parallèles tentent d’enregistrer une `Person` avec les même paramètres. Pour éviter cette situation de concurrence, l’exemple ci-dessus peut être réécrit en utilisant `get_or_create()`, comme ceci :

    obj, created = Person.objects.get_or_create(
        first_name="John",
        last_name="Lennon",
        defaults={"birthday": date(1940, 10, 9)},
    )

Tout paramètre nommé transmis à `get_or_create()` — excepté le paramètre facultatif appelé `defaults` — seront utilisés dans un appel à `get()`. Si un objet est trouvé, `get_or_create()` renvoie un tuple composé de cet objet ainsi que de `False`.

Avertissement

Cette méthode est atomique en partant du principe que la base de données assure l’unicité des paramètres nommés (voir `unique` ou `unique_together`). Si les champs utilisés dans les paramètres nommés n’ont pas de contrainte d’unicité, des appels concurrents à cette méthode peuvent aboutir à l’insertion de plusieurs lignes ayant les mêmes valeurs.

You can specify more complex conditions for the retrieved object by chaining `get_or_create()` with `filter()` and using Objets Q(). For example, to retrieve Robert or Bob Marley if either exists, and create the latter otherwise:

    from django.db.models import Q

    obj, created = Person.objects.filter(
        Q(first_name="Bob") | Q(first_name="Robert"),
    ).get_or_create(last_name="Marley", defaults={"first_name": "Bob"})

Si plusieurs objets ont été trouvés, `get_or_create()` génère `MultipleObjectsReturned`. SI un objet n’a pas été trouvé, `get_or_create()` crée une instance d’objet et l’enregistre, renvoyant un tuple composé de ce nouvel objet et de `True`. Le nouvel objet sera créé en suivant grossièrement cet algorithme

    params = {k: v for k, v in kwargs.items() if "__" not in k}
    params.update({k: v() if callable(v) else v for k, v in defaults.items()})
    obj = self.model(**params)
    obj.save()

En français, cela veut dire qu’on commence par tout paramètre nommé autre que `'defaults'` et qui ne contient pas de double soulignement (ce qui indiquerait une recherche non exacte). Puis on ajoute le contenu de `'defaults'`, surchargeant d’éventuels paramètres existants, et on utilise le résultat comme paramètres nommés de la classe de modèle. Si `defaults` contient des éléments exécutables, ils sont évalués. Comme déjà dit, il s’agit d’une simplification de l’algorithme réel, mais tous les éléments importants sont là. L’implémentation réelle contient quelques contrôles d’erreur supplémentaires et traite quelques conditions extrêmes ; si cela vous intéresse, lisez le code.

Si vous avez un champ nommé `defaults` et que vous voulez l’utiliser comme recherche exacte dans `get_or_create()`, indiquez `'defaults__exact'`, comme ceci :

    Foo.objects.get_or_create(defaults__exact="bar", defaults={"defaults": "baz"})

Le comportement d’erreur de la méthode `get_or_create()` est semblable à celui de `create()` lorsque vous définissez des clés primaires manuellement. Si un objet doit être créé et que la clé primaire existe déjà en base de données, une exception `IntegrityError` est générée.

Pour terminer, un mot sur l’utilisation de `get_or_create()` dans les vues Django. Faites attention de ne l’utiliser que dans des requêtes `POST`, sauf si vous avez des bonnes raisons de faire autrement. Les requêtes `GET` ne sont pas censées modifier des données. Il faudrait toujours utiliser `POST` lorsqu’une requête sur une page provoque des effets de bord sur les données. Pour plus de détails, lisez Safe methods dans la spécification HTTP.

Avertissement

Vous pouvez utiliser `get_or_create()` au travers d’attributs `ManyToManyField` et de relations inverses. Dans ce cas, vous allez restreindre les requêtes dans le contexte de cette relation. Certains problèmes d’intégrité peuvent apparaître si vous ne l’utilisez pas de manière cohérente.

Compte tenu des modèles suivants :

    class Chapter(models.Model):
        title = models.CharField(max_length=255, unique=True)

    class Book(models.Model):
        title = models.CharField(max_length=256)
        chapters = models.ManyToManyField(Chapter)

Vous pouvez utiliser `get_or_create()` au travers du champ `chapters` de `Book`, mais il ne considère alors que les objets dans le contexte de ce `Book`:

    >>> book = Book.objects.create(title="Ulysses")
    >>> book.chapters.get_or_create(title="Telemachus")
    (<Chapter: Telemachus>, True)
    >>> book.chapters.get_or_create(title="Telemachus")
    (<Chapter: Telemachus>, False)
    >>> Chapter.objects.create(title="Chapter 1")
    <Chapter: Chapter 1>
    >>> book.chapters.get_or_create(title="Chapter 1")
    # Raises IntegrityError

Cela se passe ainsi parce qu’il essaie d’obtenir ou de créer « Chapter 1 » au travers du livre « Ulysses », mais il ne peut faire ni l’un ni l’autre : la relation ne peut pas obtenir ce chapitre puisqu’il ne se trouve pas dans ce livre, mais il ne peut pas non plus le créer car le champ `title` doit être unique.

#### `update_or_create()`

update_or_create(defaults=None, create_defaults=None, **kwargs)

aupdate_or_create(defaults=None, create_defaults=None, **kwargs)

Version asynchrone: `aupdate_or_create()`

Une méthode utilitaire pour mettre à jour un objet avec les paramètres `kwargs` donnés, en créant un nouvel objet si nécessaire. Les paramètres `create_defaults` et `defaults` sont tous deux des dictionnaires de paires (champ, valeur). Leurs valeurs peuvent être des objets exécutables. `defaults` est utilisé pour mettre à jour l’objet, alors que `create_defaults` est utilisé pour l’opération de création. Si `create_defaults` n’est pas renseigné, ce sont les valeurs de `defaults` qui sont utilisées pour la création.

Renvoie un tuple `(objet, créé)` où `objet` est l’objet créé ou mis à jourcréé et `créé` est une valeur booléenne indiquant si un nouvel objet a été créé.

La méthode `update_or_create` essaie de récupérer un objet de la base de données en fonction des paramètres `kwargs` indiqués. Si une correspondance est trouvée, elle met à jour les champs transmis dans le dictionnaire `defaults`.

L’intention est de fournir un raccourci à la place de code répétitif. Par exemple :

    defaults = {"first_name": "Bob"}
    create_defaults = {"first_name": "Bob", "birthday": date(1940, 10, 9)}
    try:
        obj = Person.objects.get(first_name="John", last_name="Lennon")
        for key, value in defaults.items():
            setattr(obj, key, value)
        obj.save()
    except Person.DoesNotExist:
        new_values = {"first_name": "John", "last_name": "Lennon"}
        new_values.update(create_defaults)
        obj = Person(**new_values)
        obj.save()

Ce schéma devient tendancieux au fur et à mesure que le nombre de champs d’un modèle augmente. L’exemple ci-dessus peut être réécrit en utilisant `update_or_create()` comme ceci :

    obj, created = Person.objects.update_or_create(
        first_name="John",
        last_name="Lennon",
        defaults={"first_name": "Bob"},
        create_defaults={"first_name": "Bob", "birthday": date(1940, 10, 9)},
    )

Pour une description détaillée sur la manière dont les noms transmis dans `kwargs` sont résolus, voir `get_or_create()`.

Comme expliqué plus haut pour `get_or_create()`, cette méthode est sujette à un conflit de concurrence qui peut aboutir à l’insertion simultanée de plusieurs lignes si l’unicité n’est pas garantie au niveau de la base de données.

Comme `get_or_create()` et `create()`, si vous définissez des clés primaires manuellement et qu’un objet doit être créé mais que la clé primaire existe déjà en base de données, une exception `IntegrityError` est générée.

#### `bulk_create()`

bulk_create(objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None, unique_fields=None)

abulk_create(objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None, unique_fields=None)

Version asynchrone: `abulk_create()`

Cette méthode insère la liste d’objets indiquée dans la base de données de manière efficace (généralement par une seule requête, quel que soit le nombre d’objets concernés) et renvoie les objets créés dans une liste, dans le même ordre que dans l’argument :

    >>> objs = Entry.objects.bulk_create(
    ...     [
    ...         Entry(headline="This is a test"),
    ...         Entry(headline="This is only a test"),
    ...     ]
    ... )

Cette méthode présente toutefois quelques inconvénients :

- The model’s `save()` method will not be called, and the `pre_save` and `post_save` signals will not be sent.

- Elle ne fonctionne pas avec des modèles enfants dans un contexte d’héritage multitable.

- If the model’s primary key is an `AutoField` or has a `db_default` value, and `ignore_conflicts` is `False`, the primary key attribute can only be retrieved on certain databases (currently PostgreSQL, MariaDB, and SQLite). On other databases, it will not be set.

- Elle ne fonctionne pas avec les relations plusieurs-à-plusieurs.

- Elle force `objs` à être une liste, ce qui évalue entièrement `objs` s’il s’agit d’un générateur. Ce forçage permet d’inspecter tous les objets afin que tout objet ayant une clé primaire définie manuellement soit inséré en premier. Si vous souhaitez insérer des objets en lots sans évaluer d’abord le générateur entier, vous pouvez utiliser cette technique tant que les objets n’ont aucune clé primaire définie manuellement

      from itertools import islice

      batch_size = 100
      objs = (Entry(headline="Test %s" % i) for i in range(1000))
      while True:
          batch = list(islice(objs, batch_size))
          if not batch:
              break
          Entry.objects.bulk_create(batch, batch_size)

Le paramètre `batch_size` permet de contrôler le nombre d’objets créés dans une seule requête. Par défaut, les objets sont créés en lots en fonction du nombre maximal pris en charge par la base de données (SQLite et Oracle limitent le nombre de paramètres autorisés dans une requête).

Pour les bases de données qui le gèrent (toutes à l’exception d’Oracle), la définition du paramètre `ignore_conflicts` à `True` indique à la base de données d’ignorer les échecs d’insertion de lignes qui ne respectent pas les contraintes telles que les valeurs uniques dupliquées.

Pour les bases de données qui le prennent en charge (toutes sauf Oracle), la définition de `update_conflicts` à `True` indique à la base de données de mettre à jour les champs dans `update_fields` lorsque l’insertion d’une ligne échoue en cas de conflit. Avec PostgreSQL et SQLite, en plus de `update_fields`, il est requis de fournir une liste de champs `unique_fields` potentiellement en conflit.

L’activation du paramètre `ignore_conflicts` désactive la possibilité de définir la clé primaire sur chaque instance de modèle (dans le cas où la base de données le gère normalement).

Avertissement

Avec MySQL et MariaDB, quand on indique le paramètre `ignore_conflicts` à `True`, certains types d’erreurs autres que la clé dupliquée sont transformés en avertissements, même en mode strict. Par exemple : les valeurs non valables ou les violations de champ non nul. Consultez la documentation MySQL et la documentation MariaDB pour plus de détails.

#### `bulk_update()`

bulk_update(objs, fields, batch_size=None)

abulk_update(objs, fields, batch_size=None)

Version asynchrone: `abulk_update()`

Cette méthode met à jour efficacement les champs donnés sur les instances de modèles fournies, en général avec une seule requête, et renvoie le nombre d’objets mis à jour :

    >>> objs = [
    ...     Entry.objects.create(headline="Entry 1"),
    ...     Entry.objects.create(headline="Entry 2"),
    ... ]
    >>> objs[0].headline = "This is entry 1"
    >>> objs[1].headline = "This is entry 2"
    >>> Entry.objects.bulk_update(objs, ["headline"])
    2

`QuerySet.update()` est utilisé pour enregistrer les modifications, c’est donc plus efficace que de boucler sur la liste des modèles et d’appeler `save()` sur chacun d’entre eux, mais cela comporte quelques inconvénients :

- Il n’est pas possible de mettre à jour la clé primaire des modèles.

- Each model’s `save()` method isn’t called, and the `pre_save` and `post_save` signals aren’t sent.

- SI la mise à jour concerne un grand nombre de colonnes pour un grand nombre de lignes, le code SQL produit peut devenir très volumineux. Évitez cela en indiquant une valeur `batch_size` appropriée.

- Lors de la mise à jour d’un grand nombre d’objets, sachez que `bulk_update()` prépare toutes les clauses `WHEN` de chaque objet dans tous les lots avant d’exécuter la première requête. Cela pourrait surcharger la mémoire. Pour réduire cette utilisation de la mémoire, vous pouvez utiliser une approche telle que celle-ci :

      from itertools import islice

      batch_size = 100
      ids_iter = iter(range(1000))
      while ids := list(islice(ids_iter, batch_size)):
          batch = Entry.objects.filter(id__in=ids)
          for entry in batch:
              entry.headline = f"Updated headline {entry.pk}"
          Entry.objects.bulk_update(batch, ["headline"], batch_size=batch_size)

- La mise à jour de champs définis sur des instances parentes dans un contexte d’héritage multitable va générer une requête supplémentaire par parent.

- Lorsqu’un lot individuel contient des doublons, seule la première instance du lot produira une mise à jour.

- Le nombre d’objets mis à jour renvoyé par la fonction peut être plus petit que le nombre d’objets transmis. Cela peut être dû à des objets transmis à double et qui sont mis à jour dans le même lot ou à des conditions de concurrence faisant que certains objets n’existent plus en base de données.

Le paramètre `batch_size` permet de contrôler le nombre d’objets enregistrés dans une seule requête. Par défaut, tous les objets sont enregistrés en une seule instruction, à l’exception de SQLite et Oracle qui ont des restrictions sur le nombre de variables utilisables dans une requête.

#### `count()`

count()

acount()

Version asynchrone: `acount()`

Renvoie un nombre entier représentant le nombre d’objets de base de données correspondant au `QuerySet`.

Exemple :

    # Returns the total number of entries in the database.
    Entry.objects.count()

    # Returns the number of entries whose headline contains 'Lennon'
    Entry.objects.filter(headline__contains="Lennon").count()

Un appel à `count()` génère une instruction `SELECT COUNT(*)` en arrière-plan, il est donc conseiller de toujours utiliser `count()` plutôt que de charger tous les résultats en objets Python et d’appeler `len()` sur cette liste d’objets (sauf dans le cas où vous avez de toute façon besoin de charger les objets en mémoire, auquel cas `len()` sera plus rapide).

Notez que si vous souhaitez obtenir le nombre d’élément d’un `QuerySet` et que vous allez aussi exploiter ses instances de modèles (par exemple dans une itération), il est probablement plus efficace d’utiliser `len(queryset)` qui ne produira pas de requête de base de données supplémentaire comme le ferait `count()`.

Si le jeu de requête a déjà été pleinement récupéré, `count()` calculera la longueur sur ce résultat et n’effectuera pas de requête supplémentaire en base de données.

#### `in_bulk()`

in_bulk(id_list=None, *, field_name='pk')

ain_bulk(id_list=None, *, field_name='pk')

Version asynchrone: `ain_bulk()`

Accepte une liste de valeurs de champs (`id_list`) ainsi que le nom `field_name` correspondant à ces valeurs et renvoie un dictionnaire faisant correspondre chaque valeur à une instance d’objet ayant la valeur de champ donnée. Aucune exception `django.core.exceptions.ObjectDoesNotExist` n’est produite par `in_bulk`, c’est-à-dire que les valeurs de `id_list` qui ne correspondent à aucune instance seront simplement ignorées. Si `id_list` n’est pas fourni, tous les objets du jeu de requête sont renvoyés. `field_name` doit être un champ unique ou un champ distinct (si la méthode `distinct()` ne contient qu’un seul champ). `field_name` représente la clé primaire par défaut.

Exemple :

    >>> Blog.objects.in_bulk([1])
    {1: <Blog: Beatles Blog>}
    >>> Blog.objects.in_bulk([1, 2])
    {1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>}
    >>> Blog.objects.in_bulk([])
    {}
    >>> Blog.objects.in_bulk()
    {1: <Blog: Beatles Blog>, 2: <Blog: Cheddar Talk>, 3: <Blog: Django Weblog>}
    >>> Blog.objects.in_bulk(["beatles_blog"], field_name="slug")
    {'beatles_blog': <Blog: Beatles Blog>}
    >>> Blog.objects.distinct("name").in_bulk(field_name="name")
    {'Beatles Blog': <Blog: Beatles Blog>, 'Cheddar Talk': <Blog: Cheddar Talk>, 'Django Weblog': <Blog: Django Weblog>}

En passant une liste vide à `in_bulk()`, le résultat est un dictionnaire vide.

Changed in Django 6.1:

Support for chaining `in_bulk()` after `values()` or `values_list()` was added.

#### `iterator()`

iterator(chunk_size=None)

aiterator(chunk_size=None)

Version asynchrone: `aiterator()`

Evaluates the `QuerySet` (by performing the query) and returns an iterator over the results, or an asynchronous iterator if you call its asynchronous version `aiterator`.

A `QuerySet` typically caches its results internally so that repeated evaluations do not result in additional queries. In contrast, `iterator()` will read results directly, without doing any caching at the `QuerySet` level. For a `QuerySet` which returns a large number of objects that you only need to access once, this can result in better performance and a significant reduction in memory.

Notez que l’utilisation de `iterator()` sur un `QuerySet` ayant déjà été évalué force une nouvelle évaluation en répétant la requête.

`iterator()` est compatible avec les appels précédents à `prefetch_related()` tant que `chunk_size` est bien indiqué. Les grosses quantités de valeurs nécessiteront moins de requêtes pour obtenir le préchargement, mais aux dépends d’une plus grande consommation de mémoire.

Pour certaines bases de données (par ex. Oracle, SQLite), le nombre maximal de termes dans une clause SQL `IN` peut être limité. C’est pourquoi il faudrait respecter cette limite de nombre de valeurs. En particulier, lors du préchargement traversant deux ou plusieurs relations, la taille `chunk_size` devrait rester assez modeste pour que le nombre de résultats prévus pour chaque relation préchargée reste bien sous cette limite.

Tant que la requête `QuerySet` ne précharge pas d’objets liés, l’absence de valeur de `chunk_size` signifie que Django utilisera une valeur implicite par défaut de 2000.

En fonction du moteur de base de données, les résultats de requête seront soit chargés entièrement en mémoire, soit livrés en flux depuis la base de données en utilisant des curseurs côté serveur.

##### Avec des curseurs côté serveur

Oracle et PostgreSQL utilisent des curseurs côté serveur pour livrer en flux les résultats de la base de données sans charger l’entier du jeu de résultats en mémoire.

Le pilote de base de données Oracle utilise toujours des curseurs côté serveur.

Avec les curseurs côté serveur, le paramètre `chunk_size` indique le nombre de résultats à mettre en cache au niveau du pilote de base de données. L’obtention de blocs plus gros diminue le nombre d’aller-retours entre le pilote de base de données et la base de données, au détriment de la mémoire.

Avec PostgreSQL, les curseurs côté serveur ne sont utilisés que si le réglage `DISABLE_SERVER_SIDE_CURSORS` vaut `False`. Lisez Transactions groupées et curseurs côté serveur si vous utilisez un concentrateur de connexions configuré en mode concentration de transaction. Lorsque les curseurs côté serveur sont désactivés, le comportement est le même que pour les bases de données qui ne prennent pas en charge ces curseurs.

##### Sans curseurs côté serveur

MySQL ne prend pas en charge la diffusion de résultats, ce qui signifie que le pilote Python de cette base de données charge l’entier du jeu de résultats en mémoire. Ce jeu de résultats est ensuite transformé en objets lignes Python par l’adaptateur de base de données à l’aide de la méthode `fetchmany()` définie dans la PEP 249.

SQLite peut récupérer des résultats par lots avec `fetchmany()`, mais comme SQLite ne fournit pas d’isolation entre les requêtes à l’intérieur d’une connexion, soyez prudent lorsque vous écrivez dans la table qui est actuellement parcourue. Voir Isolation lors de l’utilisation de QuerySet.iterator() pour plus d’informations.

Le paramètre `chunk_size` contrôle la taille des lots que Django récupère du pilote de base de données. Des lots plus gros diminuent la surcharge de communication avec le pilote de base de données au détriment d’une légère augmentation de la consommation mémoire.

Tant que la requête `QuerySet` ne précharge pas d’objets liés, l’absence de valeur de `chunk_size` signifie que Django utilisera une valeur implicite par défaut de 2000, une valeur dérivée d’un calcul sur la liste de diffusion psycopg:

> En imaginant des lignes de 10-20 colonnes avec un mélange de données textuelles et numériques, 2000 va récupérer moins de 100 Ko de données, ce qui paraît un bon compromis entre le nombre de lignes transférées et les données à laisser tomber dans le cas d’une sortie prématurée de la boucle.

#### `latest()`

latest(*fields)

alatest(*fields)

Version asynchrone: `alatest()`

Renvoie le dernier objet de la table, en fonction du ou des champs indiqués.

Cet exemple renvoie le dernier objet `Entry` de la table, selon le champ `pub_date`:

    Entry.objects.latest("pub_date")

Il est aussi possible de choisir le dernier en fonction de plusieurs champs. Par exemple, pour choisir un `Entry` avec la date d’expiration la plus ancienne lorsque deux entrées ont la même date `pub_date`:

    Entry.objects.latest("pub_date", "-expire_date")

Le signe moins dans `'-expire_date'` indique que l’on veut trier `expire_date` dans l’ordre décroissant. Comme `latest()` obtient le dernier résultat, c’est l”`Entry` avec la date `expire_date` la plus ancienne qui est choisie.

Si la classe Meta d’un modèle définit `get_latest_by`, il est possible d’omettre tout paramètre dans `earliest()` et `latest()`. Les champs définis dans `get_latest_by` seront utilisés par défaut.

Comme `get()`, `earliest()` et `latest()` génèrent `DoesNotExist` si aucun objet ne correspond aux paramètres donnés.

Notez que `earliest()` et `latest()` n’existent que par commodité et pour une meilleure lisibilité.

`earliest()` et `latest()` peuvent renvoyer des instances avec des dates nulles.

Comme le tri est délégué à la base de données, les résultats des champs qui autorisent les valeurs nulles peuvent être triés différemment en fonction de la base de données. Par exemple, PostgreSQL et MySQL trient les valeurs nulles comme si elles étaient plus élevées que les valeurs non nulles, alors que SQLite fait l’inverse.

Il peut être souhaitable d’exclure les valeurs nulles :

    Entry.objects.filter(pub_date__isnull=False).latest("pub_date")

#### `earliest()`

earliest(*fields)

aearliest(*fields)

Version asynchrone: `aearliest()`

Fonctionne comme `latest()`, mais dans le sens inverse.

#### `first()`

first()

afirst()

Version asynchrone: `afirst()`

Returns the first object matched by the queryset, or `None` if there is no matching object. If the `QuerySet` has no ordering defined (and has not had ordering forcibly cleared by calling `order_by()` with no arguments), then the queryset is automatically ordered by the primary key. This can affect aggregation results as described in Interaction avec order_by().

Exemple :

    p = Article.objects.order_by("title", "pub_date").first()

Notez que `first()` est une méthode d’agrément ; l’extrait de code suivant est équivalent à l’exemple ci-dessus :

    try:
        p = Article.objects.order_by("title", "pub_date")[0]
    except IndexError:
        p = None

Changed in Django 6.1:

`first()` and `last()` no longer order by the primary key when ordering has been forcibly cleared by calling `order_by()` with no arguments.

#### `last()`

last()

alast()

Version asynchrone: `alast()`

Fonctionne comme `first()`, mais renvoie le dernier objet du jeu de requête.

#### `aggregate()`

aggregate(*args, **kwargs)

aaggregate(*args, **kwargs)

Version asynchrone: `aaggregate()`

Renvoie un dictionnaire de valeurs agrégées (moyennes, sommes, etc.) calculées dans le `QuerySet`. Chaque paramètre d”`aggregate()` définit une valeur qui sera incluse dans le dictionnaire renvoyé.

Les fonctions d’agrégation fournies par Django sont décrites plus loin dans Fonctions d’agrégation. Comme les agrégations sont aussi des expressions de requête, il est possible de combiner des agrégations avec d’autres agrégations ou valeurs afin de créer des agrégations complexes.

Les agrégations spécifiées par des paramètres nommés utilisent la clé comme nom d’annotation. Les paramètres anonymes seront dotés d’un nom généré automatiquement sur la base du nom de la fonction d’agrégation et du champ de modèle sur lequel porte l’agrégation. Les agrégations complexes ne peuvent pas utiliser de paramètres anonymes et doivent indiquer un paramètre nommé jouant le rôle d’alias.

Par exemple, si vous avez affaire à des articles de blog, il peut être intéressant de déterminer le nombre d’auteurs ayant écrits des articles :

    >>> from django.db.models import Count
    >>> Blog.objects.aggregate(Count("entry__authors"))
    {'entry__authors__count': 16}

En utilisant un paramètre nommé pour définir la fonction d’agrégation, vous pouvez contrôler le nom de la valeur d’agrégation dans le résultat :

    >>> Blog.objects.aggregate(number_of_authors=Count("entry__authors"))
    {'number_of_authors': 16}

Pour une présentation approfondie de l’agrégation, consultez le guide thématique sur l’agrégation.

#### `exists()`

exists()

aexists()

Version asynchrone: `aexists()`

Renvoie `True` si le `QuerySet` contient au moins un résultat, sinon `False`. Cette méthode s’efforce de lancer la requête la plus simple et rapide possible, mais la requête exécutée est quasi identique à celle du `QuerySet` normal.

`exists()` est utile pour des recherches liées à l’existence d’au moins un objet dans un `QuerySet`, particulièrement dans le contexte de `QuerySet` volumineux.

Pour savoir si un jeu de requête contient au moins un élément :

    if some_queryset.exists():
        print("There is at least one object in some_queryset")

Ce qui sera plus rapide que :

    if some_queryset:
        print("There is at least one object in some_queryset")

…mais pas de beaucoup (plus le jeu de requête est potentiellement volumineux, plus le gain sera élevé).

De plus, si `some_queryset` n’a pas encore été évalué mais que vous savez qu’il le sera à un moment donné, l’appel à `some_queryset.exists()` effectue du travail en plus (une requête pour le contrôle d’existence, plus une autre plus tard au moment de charger les résultats) par rapport à `bool(some_queryset)`, qui récupère les résultats et vérifie ensuite s’il y en a au moins un.

#### `contains()`

contains(obj)

acontains(obj)

Version asynchrone: `acontains()`

Renvoie `True` si la requête `QuerySet` contient `obj`, sinon `False`. Cette méthode s’efforce de lancer la requête la plus simple et rapide possible.

`contains()` est utile pour vérifier l’appartenance d’un objet à une requête `QuerySet`, particulièrement dans le contexte de `QuerySet` volumineuses.

Pour savoir si un jeu de requête contient un certain élément :

    if some_queryset.contains(obj):
        print("Entry contained in queryset")

Ce sera plus rapide que l’exemple suivant qui demande l’évaluation et l’itération de la totalité du jeu de requête :

    if obj in some_queryset:
        print("Entry contained in queryset")

Comme pour `exists()`, si `some_queryset` n’a pas encore été évalué mais que vous savez qu’il le sera à un moment donné, l’appel à `some_queryset.contains(obj)` va produire une requête supplémentaire dans la base de données, ce qui aboutit généralement à des performances moins bonnes.

#### `update()`

update(**kwargs)

aupdate(**kwargs)

Version asynchrone: `aupdate()`

Effectue une requête de mise à jour SQL pour les champs indiqués et renvoie le nombre de lignes affectées (qui n’est pas forcément égal au nombre de lignes mises à jour dans la mesure où certaines lignes possèdent déjà la nouvelle valeur).

Par exemple, pour désactiver les commentaires pour tous les articles de blog publiés en 2010, vous pourriez écrire cela :

    >>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)

(En supposant que votre modèle `Entry` contienne les champs `pub_date` et `comments_on`.)

Vous pouvez mettre à jour plusieurs champs ; il n’y a pas de limite. Dans l’exemple suivant, nous mettons à jour les champs `comments_on` et `headline`:

    >>> Entry.objects.filter(pub_date__year=2010).update(
    ...     comments_on=False, headline="This is old"
    ... )

La méthode `update()` est appliquée immédiatement et la seule restriction sur le `QuerySet` de mise à jour est qu’il ne peut mettre à jour que des colonnes de la table principale du modèle, pas dans des modèles liés. Par exemple, ceci n’est pas possible :

    >>> Entry.objects.update(blog__name="foo")  # Won't work!

Le filtrage basé sur des champs liés est cependant toujours possible :

    >>> Entry.objects.filter(blog__id=1).update(comments_on=True)

Vous ne pouvez pas appeler `update()` sur un `QuerySet` qui a subi une segmentation ou qui ne peut plus être filtré pour une autre raison.

La méthode `update()` renvoie le nombre de lignes affectées :

    >>> Entry.objects.filter(id=64).update(comments_on=True)
    1

    >>> Entry.objects.filter(slug="nonexistent-slug").update(comments_on=True)
    0

    >>> Entry.objects.filter(pub_date__year=2010).update(comments_on=False)
    132

Si vous n’avez qu’une ligne à mettre à jour et que vous n’avez rien à faire de spécial avec l’objet modèle, l’approche la plus efficace est d’appeler `update()`, plutôt que de charger en mémoire l’objet modèle. Par exemple, au lieu de faire cela :

    e = Entry.objects.get(id=10)
    e.comments_on = False
    e.save()

…faites ceci :

    Entry.objects.filter(id=10).update(comments_on=False)

L’utilisation d”`update()` permet aussi d’éviter une situation de concurrence où le contenu en base de données pourrait être modifié dans le court intervalle entre le chargement de l’objet et l’appel à `save()`.

MySQL ne prend pas toujours en charge les mises à jour atomiques

Avec MySQL, `QuerySet.update()` peut exécuter un `SELECT` suivi d’un `UPDATE` au lieu d’un seul `UPDATE` lors du filtrage sur des tables liées, ce qui peut introduire un conflit de concurrence si des modifications parallèles ont lieu entre les requêtes. Pour assurer l’atomicité, envisagez d’utiliser des transactions ou évitez de telles conditions de filtres avec MySQL.

Finally, realize that `update()` does an update at the SQL level and, thus, method does not call any `save()` methods on your models, nor does it emit the `pre_save` or `post_save` signals (which are a consequence of calling `Model.save()`). If you want to update a bunch of records for a model that has a custom `save()` method, loop over them and call `save()`, like this:

    for e in Entry.objects.filter(pub_date__year=2010):
        e.comments_on = False
        e.save()

##### Jeux de requête triés

L’enchaînement de `order_by()` avec `update()` n’est pris en charge que pour MariaDB et MySQL et est ignoré pour les autres bases de données. Ceci peut être utile pour mettre à jour un champ unique dans l’ordre qui est indiqué sans conflit. Par exemple

    Entry.objects.order_by("-number").update(number=F("number") + 1)

Note

La clause `order_by()` sera ignorée si elle contient des annotations, des champs hérités ou des expressions de requête traversant des relations.

#### `delete()`

delete()

adelete()

Version asynchrone: `adelete()`

Performs an SQL delete query on all rows in the `QuerySet` and returns the number of objects deleted and a dictionary with the number of deletions per object type. The return value will count instances from related models if Django is emulating cascade behavior via Python `on_delete` variants. Otherwise, for database variants such as `DB_CASCADE`, the return value will report only instances of the `QuerySet`’s model.

La suppression `delete()` s’applique immédiatement. Vous ne pouvez pas appeler `delete()` sur un `QuerySet` qui a subi une segmentation ou qui ne peut plus être filtré pour une autre raison.

Par exemple, pour supprimer tous les articles d’un blog particulier :

    >>> b = Blog.objects.get(pk=1)

    # Delete all the entries belonging to this Blog.
    >>> Entry.objects.filter(blog=b).delete()
    (4, {'blog.Entry': 2, 'blog.Entry_authors': 2})

Par défaut, les champs `ForeignKey` de Django émulent le comportement de la contrainte SQL `ON DELETE CASCADE`. En d’autres termes, tout objet possédant des clés étrangères vers les objets en cours de suppression seront également supprimés. Par exemple :

    >>> blogs = Blog.objects.all()

    # This will delete all Blogs and all of their Entry objects.
    >>> blogs.delete()
    (5, {'blog.Blog': 1, 'blog.Entry': 2, 'blog.Entry_authors': 2})

Ce comportement en cascade peut être personnalisé par le paramètre `on_delete` de `ForeignKey`.

The `delete()` method does a bulk delete and does not call any `delete()` methods on your models. It does, however, emit the `pre_delete` and `post_delete` signals for all deleted objects (including cascaded deletions). Signals won’t be sent when `DB_CASCADE` is used. Also, `delete()` doesn’t return information about objects deleted from database variants (`DB_*`) of the `on_delete` argument, e.g. `DB_CASCADE`.

Django won’t need to fetch objects into memory when deleting them in the following cases:

1. If related fields use `DB_*` options.

2. If there are no cascades and no delete signal receivers.

In these cases, Django may take a fast path and delete objects without fetching them, which can result in significantly reduced memory usage and fewer executed queries.

Les clés étrangères dont le paramètre `on_delete` vaut `DO_NOTHING` (ne rien faire) n’empêchent pas la suppression accélérée.

Notez que les requêtes générées lors de la suppression d’objets constituent un détail d’implémentation susceptible d’être modifié.

Changed in Django 6.1:

Support for the `DB_*` variants of `on_delete` attribute was added.

#### `as_manager()`

classmethod as_manager()

Méthode de classe qui renvoie une instance de `Manager` avec une copie des méthodes de `QuerySet`. Voir Création d’objet Manager avec des méthodes de QuerySet pour plus de détails.

Notez qu’à l’inverse des autres entrées de cette section, celle-ci ne possède pas de variante asynchrone car elle n’exécute pas de requête.

#### `explain()`

explain(format=None, **options)

aexplain(format=None, **options)

Version asynchrone: `aexplain()`

Renvoie une chaîne contenant le plan d’exécution de la requête `QuerySet`, qui présente comment la base de données va exécuter la requête, y compris les index ou jointures qui seraient utilisés. La connaissance de ces détails peut aider à améliorer les performances des requêtes lentes.

Par exemple, avec PostgreSQL :

    >>> print(Blog.objects.filter(title="My Blog").explain())
    Seq Scan on blog  (cost=0.00..35.50 rows=10 width=12)
      Filter: (title = 'My Blog'::bpchar)

Le résultat diffère significativement entre les base de données.

`explain()` est pris en charge par tous les moteurs de base de données intégrés à l’exception d’Oracle car une implémentation pour ce dernier n’est pas évidente.

The `format` parameter changes the output format from the database’s default, which is usually text-based. PostgreSQL supports `'TEXT'`, `'JSON'`, `'YAML'`, and `'XML'` formats. MariaDB and MySQL support `'TEXT'` (also called `'TRADITIONAL'`) and `'JSON'` formats. MySQL 8.0.16+ also supports an improved `'TREE'` format, which is similar to PostgreSQL’s `'TEXT'` output and is used by default, if supported.

Certaines bases de données acceptent des options pouvant renvoyer plus d’informations sur la requête. Passez ces options sous forme de paramètres nommés. Par exemple, avec PostgreSQL :

    >>> print(Blog.objects.filter(title="My Blog").explain(verbose=True, analyze=True))
    Seq Scan on public.blog  (cost=0.00..35.50 rows=10 width=12) (actual time=0.004..0.004 rows=10 loops=1)
      Output: id, title
      Filter: (blog.title = 'My Blog'::bpchar)
    Planning time: 0.064 ms
    Execution time: 0.058 ms

On some databases, flags may cause the query to be executed which could have adverse effects on your database. For example, the `ANALYZE` flag supported by MariaDB, MySQL, and PostgreSQL could result in changes to data if there are triggers or if a function is called, even for a `SELECT` query.

### Recherches dans les champs

La recherche dans les champs est ce qui constitue le cœur des clauses SQL `WHERE`. La syntaxe s’exprime par des paramètres nommés dans les méthodes `filter()`, `exclude()` et `get()` de `QuerySet`.

Pour une introduction sur ce sujet, consultez la documentation sur les requêtes de modèles et de base de données.

Les recherches fournies par Django sont présentées ci-dessous. Il est également possible d’écrire des recherches personnalisées pour les champs de modèles.

Par commodité, lorsqu’aucune recherche particulière n’est indiquée (comme dans `Entry.objects.get(id=14)`), Django suppose que la recherche souhaitée est `exact`.

#### `exact`

Exact match. If the value provided for comparison is `None`, it will be interpreted as an SQL `NULL` (see `isnull` for more details). `Key and index lookups` are exceptions: they interpret `None` as JSON `null` instead.

Exemples :

    Entry.objects.get(id__exact=14)
    Entry.objects.get(id__exact=None)

Équivalence en SQL :

    SELECT ... WHERE id = 14;
    SELECT ... WHERE id IS NULL;

Comparaisons MySQL

Avec MySQL, le paramètre « collation » d’une table de base de données détermine si les comparaisons `exact` sont sensibles à la casse. Il s’agit d’un réglage de base de données, pas de Django. Il est possible de configurer vos tables MySQL afin qu’elles utilisent des comparaisons sensibles à la casse, mais cela implique certains compromis. Pour plus d’informations à ce sujet, consultez la section collation dans la documentation des bases de données.

#### `iexact`

Correspondance exacte insensible à la casse. Si la valeur fournie pour la comparaison vaut `None`, elle sera interprétée comme un `NULL` SQL (voir `isnull` pour plus de détails).

Exemple :

    Blog.objects.get(name__iexact="beatles blog")
    Blog.objects.get(name__iexact=None)

Équivalence en SQL :

    SELECT ... WHERE name ILIKE 'beatles blog';
    SELECT ... WHERE name IS NULL;

Notez que `'Beatles Blog'`, `'beatles blog'`, `'BeAtLes BLoG'`, etc. correspondent tous à la première recherche.

Utilisateurs de SQLite

Lors de l’utilisation du moteur SQLite et de chaînes non ASCII, il faut tenir compte des notes de base de données au sujet de la comparaison de chaînes. SQLite n’effectue pas de recherches insensibles à la casse pour des chaînes non ASCII.

#### `contains`

Test d’inclusion sensible à la casse.

Exemple :

    Entry.objects.get(headline__contains="Lennon")

Équivalent SQL :

    SELECT ... WHERE headline LIKE '%Lennon%';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Notez que le titre (`headline`) `'Lennon honored today'` correspondrait à cette recherche, mais pas `'lennon honored today'`.

Utilisateurs de SQLite

SQLite ne prend pas en charge les instructions `LIKE` sensibles à la casse ; `contains` se comporte comme `icontains` pour SQLite. Consultez les notes de bases de données pour plus d’informations.

#### `icontains`

Test d’inclusion insensible à la casse.

Exemple :

    Entry.objects.get(headline__icontains="Lennon")

Équivalent SQL :

    SELECT ... WHERE headline ILIKE '%Lennon%';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Utilisateurs de SQLite

Lors de l’utilisation du moteur SQLite et de chaînes non ASCII, il faut tenir compte des notes de base de données au sujet de la comparaison de chaînes.

#### `in`

Dans un itérable donné ; souvent une liste, un tuple ou un jeu de requête. Ce n’est pas courant, mais des chaînes (qui sont aussi des itérables) sont acceptées.

Exemples :

    Entry.objects.filter(id__in=[1, 3, 4])
    Entry.objects.filter(headline__in="abc")

Équivalence en SQL :

    SELECT ... WHERE id IN (1, 3, 4);
    SELECT ... WHERE headline IN ('a', 'b', 'c');

Vous pouvez également utiliser un jeu de requête pour évaluer dynamiquement la liste des valeurs au lieu de fournir une liste de valeurs littérales :

    inner_qs = Blog.objects.filter(name__contains="Cheddar")
    entries = Entry.objects.filter(blog__in=inner_qs)

Ce jeu de requête sera évalué sous forme d’instruction de sous-sélection :

    SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

Si vous fournissez un `QuerySet` résultant d’un appel à `values()` ou à `values_list()` comme valeur d’une requête `__in`, vous devez vous assurer que vous extrayez un seul champ du résultat. Par exemple, ceci fonctionnera (filtrage sur les noms de blogs) :

    inner_qs = Blog.objects.filter(name__contains="Ch").values("name")
    entries = Entry.objects.filter(blog__name__in=inner_qs)

Cet exemple générera une exception, car la requête imbriquée extrait deux valeurs de champ, alors qu’il n’en faut qu’une seule :

    # Bad code! Will raise a TypeError.
    inner_qs = Blog.objects.filter(name__contains="Ch").values("name", "id")
    entries = Entry.objects.filter(blog__name__in=inner_qs)

Considérations sur la performance

Soyez prudent avec les requêtes imbriquées ; il s’agit de bien comprendre les enjeux au niveau des performances du serveur de base de données (en cas de doute, faites des tests de performance). Certains moteurs de base de données, plus particulièrement MySQL, n’optimisent pas très bien les sous-requêtes. Dans ces situations, il est plus efficace d’extraire les valeurs sous forme de liste puis de les transmettre à la seconde requête. En clair, effectuer deux requêtes au lieu d’une seule :

    values = Blog.objects.filter(name__contains="Cheddar").values_list("pk", flat=True)
    entries = Entry.objects.filter(blog__in=list(values))

Remarquez l’appel `list()` autour du `QuerySet` Blog pour forcer l’exécution de la première requête. Sans cela, une sous-requête serait exécutée, car Les objects QuerySet sont différés.

#### `gt`

Plus grand que.

Exemple :

    Entry.objects.filter(id__gt=4)

Équivalent SQL :

    SELECT ... WHERE id > 4;

#### `gte`

Plus grand ou égal à.

#### `lt`

Plus petit que.

#### `lte`

Plus petit ou égal à.

#### `startswith`

Commence par (sensible à la casse).

Exemple :

    Entry.objects.filter(headline__startswith="Lennon")

Équivalent SQL :

    SELECT ... WHERE headline LIKE 'Lennon%';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

SQLite ne prend pas en charge les instructions `LIKE` sensibles à la casse ; `startswith` se comporte comme `istartswith` pour SQLite.

#### `istartswith`

Commence par (non sensible à la casse).

Exemple :

    Entry.objects.filter(headline__istartswith="Lennon")

Équivalent SQL :

    SELECT ... WHERE headline ILIKE 'Lennon%';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Utilisateurs de SQLite

Lors de l’utilisation du moteur SQLite et de chaînes non ASCII, il faut tenir compte des notes de base de données au sujet de la comparaison de chaînes.

#### `endswith`

Se termine par (sensible à la casse).

Exemple :

    Entry.objects.filter(headline__endswith="Lennon")

Équivalent SQL :

    SELECT ... WHERE headline LIKE '%Lennon';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Utilisateurs de SQLite

SQLite ne prend pas en charge les instructions `LIKE` sensibles à la casse ; `endswith` se comporte comme `iendswith` pour SQLite. Consultez les notes de bases de données pour plus d’informations.

#### `iendswith`

Se termine par (non sensible à la casse).

Exemple :

    Entry.objects.filter(headline__iendswith="Lennon")

Équivalent SQL :

    SELECT ... WHERE headline ILIKE '%Lennon';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Utilisateurs de SQLite

Lors de l’utilisation du moteur SQLite et de chaînes non ASCII, il faut tenir compte des notes de base de données au sujet de la comparaison de chaînes.

#### `range`

Test d’intervalle (inclusif).

Exemple :

    import datetime

    start_date = datetime.date(2005, 1, 1)
    end_date = datetime.date(2005, 3, 31)
    Entry.objects.filter(pub_date__range=(start_date, end_date))

Équivalent SQL :

    SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

Vous pouvez utiliser `range` partout là ou vous pouvez utiliser `BETWEEN` en SQL — pour les dates, les nombres et même les caractères.

Avertissement

Le filtrage sur un champ `DateTimeField` avec des dates n’inclura pas les objets du dernier jour, car les limites sont interprétées comme « minuit à la date indiquée ». Si `pub_date` était un champ `DateTimeField`, l’expression ci-dessus correspondrait au code SQL suivant :

    SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';

De manière générale, il n’est pas possible de mélanger des objets dates et dates/heures.

#### `date`

Pour les champs date/heure, force la valeur à une date. Cette expression peut être suivie d’autres expressions de champs. Accepte une valeur date.

Exemple :

    Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
    Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

(Nous n’avons pas inclus de code SQL équivalent pour cette recherche car l’implémentation de la requête correspondante varie beaucoup selon le moteur de base de données.)

Lorsque `USE_TZ` vaut `True`, les champs sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `year`

Pour les champs date et date/heure, une correspondance exacte de l’année. Cette expression peut être suivie d’autres expressions de champs. Accepte une année comme nombre entier.

Exemple :

    Entry.objects.filter(pub_date__year=2005)
    Entry.objects.filter(pub_date__year__gte=2005)

Équivalent SQL :

    SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
    SELECT ... WHERE pub_date >= '2005-01-01';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `iso_year`

Pour les champs date et date/heure, une correspondance exacte de l’année avec numéros de semaine ISO 8601. Cette expression peut être suivie d’autres expressions de champs. Accepte une année comme nombre entier.

Exemple :

    Entry.objects.filter(pub_date__iso_year=2005)
    Entry.objects.filter(pub_date__iso_year__gte=2005)

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `month`

Pour les champs date et date/heure, une correspondance exacte du mois. Cette expression peut être suivie d’autres expressions de champs. Accepte un nombre entier, de 1 (janvier) à 12 (décembre).

Exemple :

    Entry.objects.filter(pub_date__month=12)
    Entry.objects.filter(pub_date__month__gte=6)

Équivalent SQL :

    SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
    SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `day`

Pour les champs date et date/heure, une correspondance exacte du jour. Cette expression peut être suivie d’autres expressions de champs. Accepte un jour comme nombre entier.

Exemple :

    Entry.objects.filter(pub_date__day=3)
    Entry.objects.filter(pub_date__day__gte=3)

Équivalent SQL :

    SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
    SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Notez que cela correspond à tout élément dont le champ `pub_date` est égal au troisième jour du mois, comme le 3 janvier, le 3 juillet, etc.

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `week`

Pour des champs date et date/heure, renvoie le numéro de semaine (1-52 ou 53) selon ISO-8601, c’est-à-dire que les semaines commencent un lundi et que la première semaine contient le premier jeudi de l’année.

Exemple :

    Entry.objects.filter(pub_date__week=52)
    Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)

(Nous n’avons pas inclus de code SQL équivalent pour cette recherche car l’implémentation de la requête correspondante varie beaucoup selon le moteur de base de données.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `week_day`

Pour les champs date et date/heure, une correspondance exacte du « jour de la semaine ». Cette expression peut être suivie d’autres expressions de champs.

Accepte un nombre entier représentant le jour de la semaine, de 1 (dimanche) à 7 (samedi).

Exemple :

    Entry.objects.filter(pub_date__week_day=2)
    Entry.objects.filter(pub_date__week_day__gte=2)

(Nous n’avons pas inclus de code SQL équivalent pour cette recherche car l’implémentation de la requête correspondante varie beaucoup selon le moteur de base de données.)

Notez que cela correspond à tout élément dont le champ `pub_date` est un lundi (jour 2 de la semaine), sans tenir compte du mois ou de l’année. Les jours de la semaine sont indexés de 1 (dimanche) à 7 (samedi).

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `iso_week_day`

Pour les champs date et date/heure, une correspondance exacte du jour de la semaine ISO 8601. Cette expression peut être suivie d’autres expressions de champs.

Accepte un nombre entier représentant le jour de la semaine, de 1 (lundi) à 7 (dimanche).

Exemple :

    Entry.objects.filter(pub_date__iso_week_day=1)
    Entry.objects.filter(pub_date__iso_week_day__gte=1)

(Nous n’avons pas inclus de code SQL équivalent pour cette recherche car l’implémentation de la requête correspondante varie beaucoup selon le moteur de base de données.)

Notez que cela correspond à tout élément dont le champ `pub_date` est un lundi (jour 2 de la semaine), sans tenir compte du mois ou de l’année. Les jours de la semaine sont indexés de 1 (lundi) à 7 (dimanche).

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `quarter`

Pour les champs date et date/heure, une correspondance de « trimestre annuel ». Cette expression peut être suivie d’autres expressions de champs. Accepte une valeur nombre entier entre 1 et 4 représentant le trimestre de l’année.

Exemple pour obtenir les lignes du deuxième trimestre (1er avril au 30 juin)

    Entry.objects.filter(pub_date__quarter=2)

(Nous n’avons pas inclus de code SQL équivalent pour cette recherche car l’implémentation de la requête correspondante varie beaucoup selon le moteur de base de données.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `time`

Pour les champs date/heure, force la valeur à une heure. Cette expression peut être suivie d’autres expressions de champs. Accepte une valeur `datetime.time`.

Exemple :

    Entry.objects.filter(pub_date__time=datetime.time(14, 30))
    Entry.objects.filter(pub_date__time__range=(datetime.time(8), datetime.time(17)))

(Nous n’avons pas inclus de code SQL équivalent pour cette recherche car l’implémentation de la requête correspondante varie beaucoup selon le moteur de base de données.)

Lorsque `USE_TZ` vaut `True`, les champs sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `hour`

Pour les champs date/heure et heure, une correspondance exacte de l’heure. Cette expression peut être suivie d’autres expressions de champs. Accepte un nombre entier entre 0 et 23.

Exemple :

    Event.objects.filter(timestamp__hour=23)
    Event.objects.filter(time__hour=5)
    Event.objects.filter(timestamp__hour__gte=12)

Équivalent SQL :

    SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
    SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
    SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `minute`

Pour les champs date/heure et heure, une correspondance exacte de la minute. Cette expression peut être suivie d’autres expressions de champs. Accepte un nombre entier entre 0 et 59.

Exemple :

    Event.objects.filter(timestamp__minute=29)
    Event.objects.filter(time__minute=46)
    Event.objects.filter(timestamp__minute__gte=29)

Équivalent SQL :

    SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
    SELECT ... WHERE EXTRACT('minute' FROM time) = '46';
    SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `second`

Pour les champs date/heure et heure, une correspondance exacte de la seconde. Cette expression peut être suivie d’autres expressions de champs. Accepte un nombre entier entre 0 et 59.

Exemple :

    Event.objects.filter(timestamp__second=31)
    Event.objects.filter(time__second=2)
    Event.objects.filter(timestamp__second__gte=31)

Équivalent SQL :

    SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
    SELECT ... WHERE EXTRACT('second' FROM time) = '2';
    SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';

(La syntaxe SQL exacte varie d’un moteur de base de données à l’autre.)

Lorsque `USE_TZ` vaut `True`, les champs date/heure sont convertis dans le fuseau horaire en cours avant le filtrage. Cela nécessite la présence des définitions de fuseaux horaires dans la base de données.

#### `isnull`

Accepte `True` ou `False`, ce qui correspond respectivement aux instructions SQL `IS NULL` et `IS NOT NULL`.

Exemple :

    Entry.objects.filter(pub_date__isnull=True)

Équivalent SQL :

    SELECT ... WHERE pub_date IS NULL;

#### `regex`

Recherche par expression régulière, sensible à la casse.

La syntaxe d’expression régulière est celle du moteur de base de données utilisé. Pour SQLite qui ne prend pas en charge nativement les expressions régulières, cette fonctionnalité est fournie par une fonction (Python) `REGEXP` définie par l’utilisateur, et la syntaxe d’expression régulière est par conséquent celle du module `re` de Python.

Exemple :

    Entry.objects.get(title__regex=r"^(An?|The) +")

Équivalence en SQL :

    SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL

    SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- Oracle

    SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL

    SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite

Il est recommandé d’utiliser des chaînes brutes (par ex. `r'foo'` au lieu de `'foo'`) pour transmettre des expressions régulières.

#### `iregex`

Recherche par expression régulière, insensible à la casse.

Exemple :

    Entry.objects.get(title__iregex=r"^(an?|the) +")

Équivalence en SQL :

    SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL

    SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle

    SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL

    SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite

### Fonctions d’agrégation

Django fournit les fonctions d’agrégation suivantes dans le module `django.db.models`. Pour plus de détails sur l’usage de ces fonctions, consultez le guide thématique sur l’agrégation. Consultez la documentation de `Aggregate` pour apprendre à créer vos propres agrégations.

Avertissement

SQLite ne sait pas nativement gérer des agrégations sur des champs date/heure. La raison est qu’il n’existe pas de vrais champs date/heure dans SQLite et que Django émule actuellement ces fonctions en utilisant un champ texte. Si vous essayez d’effectuer des agrégations sur des champs date/heure avec SQLite, vous obtiendrez l’exception `NotSupportedError`.

Jeux de requête ou groupes vides

Les fonctions d’agrégation renvoient `None` lorsqu’elles sont utilisées avec un objet `QuerySet` ou un groupe vide. Par exemple, la fonction d’agrégation `Sum` (somme) renvoie `None` au lieu de `0` si le jeu de requête ne contient pas d’élément ou pour tout groupe vide dans un jeu de requête non vide. Pour renvoyer une autre valeur dans ce cas de figure, définissez l’argument `default`. `Count` est une exception à cette règle, il renvoie `0` quand le jeu de requête est vide car `Count` ne prend pas en charge l’argument `default`.

Toutes les agrégations partagent les paramètres suivants :

#### `expressions`

Des chaînes référençant des champs du modèle, des transformations du champ ou des expressions de requête.

#### `output_field`

Un paramètre facultatif représentant le champ de modèle de la valeur renvoyée.

Note

Lors de la combinaison de plusieurs types de champs, Django ne peut déterminer le type de résultat `output_field` qui si tous les champs sont du même type. Sinon, vous devez indiquer `output_field` vous-même.

#### `filter`

An optional Q object that’s used to filter the rows that are aggregated.

Voir Agrégation conditionnelle et Filtrage sur les annotations pour des exemples d’utilisation.

#### `default`

Un argument facultatif permettant de définir une valeur à utiliser comme valeur par défaut lorsque la requête (ou le groupement) ne renvoie aucune ligne.

#### `**extra`

Paramètres nommés qui peuvent fournir du contexte supplémentaire pour le code SQL généré par l’agrégation.

#### `AnyValue`

New in Django 6.0.

class AnyValue(expression, output_field=None, filter=None, default=None, **extra)

  Renvoie une valeur arbitraire à partir des valeurs saisies non nulles.

  - Alias par défaut : `<field>__anyvalue`

  - Type de la valeur renvoyée : identique au champ de départ, ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

  Exemple d’utilisation :

      >>> # Get average rating for each year along with a sample headline
      >>> # from that year.
      >>> from django.db.models import AnyValue, Avg, F, Q
      >>> sample_headline = AnyValue("headline")
      >>> Entry.objects.values(
      ...     pub_year=F("pub_date__year"),
      ... ).annotate(
      ...     avg_rating=Avg("rating"),
      ...     sample_headline=sample_headline,
      ... )

      >>> # Get a sample headline from each year with rating greater than 4.5.
      >>> sample_headline = AnyValue(
      ...     "headline",
      ...     filter=Q(rating__gt=4.5),
      ... )
      >>> Entry.objects.values(
      ...     pub_year=F("pub_date__year"),
      ... ).annotate(
      ...     avg_rating=Avg("rating"),
      ...     sample_headline=sample_headline,
      ... )

  Pris en charge avec SQLite, MySQL, Oracle et PostgreSQL 16+.

  MySQL quand `ONLY_FULL_GROUP_BY` est activé

  When the `ONLY_FULL_GROUP_BY` SQL mode is enabled on MySQL it may be necessary to use `AnyValue` if an aggregation includes a mix of aggregate and non-aggregate functions. Using `AnyValue` allows the non-aggregate function to be referenced in the select list when database cannot determine that it is functionally dependent on the columns in the group by clause. See the aggregation documentation for more details.

#### `Avg`

class Avg(expression, output_field=None, distinct=False, filter=None, default=None, **extra)

  Renvoie la valeur moyenne de l’expression indiquée, qui doit être de type numérique, sauf si vous indiquez un champ `output_field` différent.

  - Alias par défaut : `<champ>__avg`

  - Type de la valeur renvoyée : `float` si la valeur d’entrée est `int`, sinon identique au champ de départ, ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

  distinct

    Facultatif. Si `distinct=True`, `Avg` renvoie la valeur moyenne de valeurs uniques. Cela correspond au code SQL `AVG(DISTINCT <field>)`. La valeur par défaut est `False`.

#### `BitAnd`

class BitAnd(expression, filter=None, default=None, **extra)
  New in Django 6.1.

  Renvoie un entier `int` résultat de l’opération `AND` bit-à-bit de toutes les valeurs non nulles, ou `default` si toutes les valeurs sont nulles.

  The `default` parameter is not supported on MariaDB, MySQL, and Oracle.

#### `BitOr`

class BitOr(expression, filter=None, default=None, **extra)
  New in Django 6.1.

  Renvoie un entier `int` résultat de l’opération `OR` bit-à-bit de toutes les valeurs non nulles, ou `default` si toutes les valeurs sont nulles.

  The `default` parameter is not supported on MariaDB, MySQL, and Oracle.

#### `BitXor`

class BitXor(expression, filter=None, default=None, **extra)
  New in Django 6.1.

  Returns an `int` of the bitwise `XOR` of all non-null input values, or `default` if all values are null.

  The `default` parameter is not supported on MariaDB, MySQL, and Oracle.

#### `Count`

class Count(expression, distinct=False, filter=None, **extra)

  Renvoie le nombre d’objets qui sont liés au travers de l’expression fournie. `Count('*')` est équivalent à l’expression SQL `COUNT(*)`.

  - Alias par défaut : `<champ>__count`

  - Type de la valeur renvoyée : `int`

  distinct

    Facultatif. Si `distinct=True`, le dénombrement ne tient compte que des instances uniques. Cela correspond au code SQL `COUNT(DISTINCT <field>)`. La valeur par défaut est `False`.

  Note

  Le paramètre `default` n’est pas pris en charge.

#### `Max`

class Max(expression, output_field=None, filter=None, default=None, **extra)

  Renvoie la valeur maximale de l’expression donnée.

  - Alias par défaut : `<champ>__max`

  - Type de la valeur renvoyée : identique au champ de départ, ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

#### `Min`

class Min(expression, output_field=None, filter=None, default=None, **extra)

  Renvoie la valeur minimale de l’expression donnée.

  - Alias par défaut : `<champ>__min`

  - Type de la valeur renvoyée : identique au champ de départ, ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

#### `StdDev`

class StdDev(expression, output_field=None, sample=False, filter=None, default=None, **extra)

  Renvoie la déviation standard des données contenues dans l’expression donnée.

  - Alias par défaut : `<champ>__stddev`

  - Type de la valeur renvoyée : `float` si la valeur d’entrée est `int`, sinon identique au champ de départ, ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

  sample

    Facultatif. Par défaut, `StdDev` renvoie la déviation standard de population. Cependant, si `sample=True`, la valeur renvoyée sera la déviation standard d’échantillon.

#### `Sum`

class Sum(expression, output_field=None, distinct=False, filter=None, default=None, **extra)

  Calcule la somme de toutes les valeurs de l’expression donnée.

  - Alias par défaut : `<champ>__sum`

  - Type de la valeur renvoyée : identique au champ de départ, ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

  distinct

    Facultatif. Si `distinct=True`, `Sum` renvoie la somme des valeurs uniques. Cela correspond au code SQL `SUM(DISTINCT <field>)`. La valeur par défaut est False`.

#### `Variance`

class Variance(expression, output_field=None, sample=False, filter=None, default=None, **extra)

  Renvoie la variance des données de l’expression donnée.

  - Alias par défaut : `<champ>__variance`

  - Type de la valeur renvoyée : `float` si la valeur d’entrée est `int`, sinon identique au champ de départ, ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

  sample

    Facultatif. Par défaut, `Variance` renvoie la variance de population. Cependant, si `sample=True`, la valeur renvoyée sera la variance d’échantillon.

#### `StringAgg`

New in Django 6.0.

class StringAgg(expression, delimiter, output_field=None, distinct=False, filter=None, order_by=None, default=None, **extra)

  Renvoie les valeurs d’entrée concaténées dans une chaîne, séparées par la chaîne `delimiter`, ou `default` s’il n’y a aucune valeur.

  - Alias par défaut : `<field>__stringagg`

  - Type de la valeur renvoyée : `string` ou `output_field` s’il est indiqué. Si le jeu de requête ou le groupe est vide, c’est la valeur de `default` qui est renvoyée.

  delimiter

    A `Value` or expression representing the string that should separate each of the values. For example, `Value(",")`. (On SQLite, the literal delimiter `Value(",")` is the only delimiter compatible with `distinct=True`.)

    Changed in Django 6.1:

    Support for using `distinct=True` with a delimiter of `Value(",")` on SQLite was added.

## Outils liés aux requêtes

Cette section présente du contenu de référence pour des outils liés aux requêtes et non documentés ailleurs.

### Objets `Q()`

class Q

Un objet `Q()` représente une condition SQL pouvant être utilisée dans les opérations liées aux bases de données. C’est le même principe que pour les objets `F()` qui représentent la valeur d’un champ de modèle ou d’une annotation. Ils rendent possible la définition et la réutilisation de conditions. Leur logique peut être inversée en utilisant l’opérateur `~` (`NOT`), ou combinée avec des opérateurs tels que `|` (`OR`), `&` (`AND`) et `^` (`XOR`). Voir Requêtes complexes avec des objets Q.

### Objets `Prefetch()`

class Prefetch(lookup, queryset=None, to_attr=None)

L’objet `Prefetch()` peut être utilisé pour contrôler le fonctionnement de `prefetch_related()`.

Le paramètre `lookup` décrit les relations à suivre et fonctionne de la même façon que les recherches basées sur des chaînes transmises à `prefetch_related()`. Par exemple :

    >>> from django.db.models import Prefetch
    >>> Question.objects.prefetch_related(Prefetch("choice_set")).get().choice_set.all()
    <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
    # This will only execute two queries regardless of the number of Question
    # and Choice objects.
    >>> Question.objects.prefetch_related(Prefetch("choice_set"))
    <QuerySet [<Question: What's up?>]>

Le paramètre `queryset` fournit un jeu `QuerySet` de base pour la recherche concernée. C’est utile pour filtrer de manière plus précise l’opération de préchargement ou pour appeler `select_related()` à partir de la relation préchargée, ce qui réduira encore plus le nombre de requêtes :

    >>> voted_choices = Choice.objects.filter(votes__gt=0)
    >>> voted_choices
    <QuerySet [<Choice: The sky>]>
    >>> prefetch = Prefetch("choice_set", queryset=voted_choices)
    >>> Question.objects.prefetch_related(prefetch).get().choice_set.all()
    <QuerySet [<Choice: The sky>]>

Le paramètre `to_attr` attribue le résultat de l’opération de préchargement à un attribut personnalisé :

    >>> prefetch = Prefetch("choice_set", queryset=voted_choices, to_attr="voted_choices")
    >>> Question.objects.prefetch_related(prefetch).get().voted_choices
    <QuerySet [<Choice: The sky>]>
    >>> Question.objects.prefetch_related(prefetch).get().choice_set.all()
    <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

Note

Quand `to_attr` est utilisé, le résultat préchargé est stocké dans une liste. Cela peut apporter une amélioration de rapidité significative par rapport aux appels `prefetch_related` traditionnels qui stockent les résultats en cache dans une instance `QuerySet`.

### `prefetch_related_objects()`

prefetch_related_objects(model_instances, *related_lookups)

aprefetch_related_objects(model_instances, *related_lookups)

Version asynchrone: `aprefetch_related_objects()`

Précharge les expression de requête données pour la liste d’instances de modèles. C’est utile dans du code qui reçoit une liste d’instances de modèles et non pas un `QuerySet`; par exemple, lors de la récupération de modèles depuis un cache ou lors d’une instanciation manuelle.

Passez une liste d’instances de modèles (toutes de la même classe et avec la capacité d’itérations multiples) et les requêtes ou objets `Prefetch` que vous souhaitez précharger. Par exemple :

    >>> from django.db.models import prefetch_related_objects
    >>> restaurants = fetch_top_restaurants_from_cache()  # A list of Restaurants
    >>> prefetch_related_objects(restaurants, "pizzas__toppings")

Lors de l’utilisation de plusieurs bases de données avec `prefetch_related_objects`, la requête de préchargement utilisera la base de données associée à l’instance de modèle. Ce comportement peut être remplacé en utilisant un jeu de requête personnalisé dans l’expression de liaison.

### Objets `FilteredRelation()`

class FilteredRelation(relation_name, *, condition=Q())
  relation_name

    Le nom du champ sur lequel portera le filtrage de la relation.

  condition

    A Q object to control the filtering.

`FilteredRelation` est utilisé avec `annotate()` pour créer une clause `ON` lorsque un `JOIN` est effectué. Il n’agit pas sur la relation par défaut mais sur le nom d’annotation (`pizzas_vegetarian` dans l’exemple ci-dessous).

Par exemple, pour trouver tous les restaurants ayant des pizzas végétariennes avec `'mozarella'` dans le nom :

    >>> 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")

S’il y a beaucoup de pizzas, ce jeu de requête sera plus efficace que :

    >>> Restaurant.objects.filter(
    ...     pizzas__vegetarian=True,
    ...     pizzas__name__icontains="mozzarella",
    ... )

car le filtrage dans la clause `WHERE` du premier jeu de requête ne s’appliquera que sur les pizzas végétariennes.

`FilteredRelation` ne prend pas en charge :

- `QuerySet.only()` et `prefetch_related()`.

- Une `GenericForeignKey` héritée d’un modèle parent.