Référence de l’API QuerySetLien vers cette rubrique

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ésLien vers cette rubrique

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 :

    Code
    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:

    Code
    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 :

    Code
    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 :

    Code
    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 »Lien vers cette rubrique

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 :

Python console
>>> 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).

API QuerySetLien vers cette rubrique

Voici la déclaration formelle d’un QuerySet:

class QuerySet(model=None, query=None, using=None, hints=None)Lien vers cette définition

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 :

orderedLien vers cette définition

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_orderedLien vers cette définition

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.

dbLien vers cette définition

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

Méthodes renvoyant de nouveaux QuerySetLien vers cette rubrique

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.

filter()Lien vers cette rubrique

filter(*args, **kwargs)Lien vers cette définition

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()Lien vers cette rubrique

exclude(*args, **kwargs)Lien vers cette définition

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 » :

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

En termes SQL, cela donne :

SQL
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 »

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

En termes SQL, cela donne :

SQL
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()Lien vers cette rubrique

annotate(*args, **kwargs)Lien vers cette définition

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 :

Python console
>>> 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 :

Python console
>>> 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()Lien vers cette rubrique

alias(*args, **kwargs)Lien vers cette définition

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 :

Python console
>>> 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:

Code
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()Lien vers cette rubrique

order_by(*fields)Lien vers cette définition

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 :

Code
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 :

Code
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 :

Code
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 :

Code
Entry.objects.order_by("blog")

… est identique à :

Code
Entry.objects.order_by("blog__id")

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

Code
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 :

Code
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.

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 :

Code
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:

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

reverse()Lien vers cette rubrique

reverse()Lien vers cette définition

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 :

Code
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()Lien vers cette rubrique

distinct(*fields)Lien vers cette définition

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.

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.

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

Python console
>>> 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 [...]>

values()Lien vers cette rubrique

values(*fields, **expressions)Lien vers cette définition

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 :

Python console
# 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 :

Python console
>>> 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():

Python console
>>> 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 :

Python console
>>> 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 :

Python console
>>> 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 :

    Python console
    >>> 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 :

    Python console
    >>> 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 :

Code
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:

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

values_list()Lien vers cette rubrique

values_list(*fields, flat=False, named=False)Lien vers cette définition

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 :

Python console
>>> 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 :

Python console
>>> 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():

Python console
>>> 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():

Python console
>>> 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:

Python console
>>> 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 :

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

dates()Lien vers cette rubrique

dates(field, kind, order='ASC')Lien vers cette définition

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 :

Python console
>>> 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()Lien vers cette rubrique

datetimes(field_name, kind, order='ASC', tzinfo=None)Lien vers cette définition

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.

none()Lien vers cette rubrique

none()Lien vers cette définition

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 :

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

all()Lien vers cette rubrique

all()Lien vers cette définition

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()Lien vers cette rubrique

union(*other_qs, all=False)Lien vers cette définition

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

Code
>>> 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 :

Python console
>>> 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()Lien vers cette rubrique

intersection(*other_qs)Lien vers cette définition

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

Python console
>>> qs1.intersection(qs2, qs3)

Voir union() concernant quelques restrictions.

difference()Lien vers cette rubrique

difference(*other_qs)Lien vers cette définition

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 :

Python console
>>> qs1.difference(qs2, qs3)

Voir union() concernant quelques restrictions.

fetch_mode()Lien vers cette rubrique

fetch_mode(mode)Lien vers cette définition

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:

Python
from django.db import models

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

See more in the fetch mode topic guide.

extra()Lien vers cette rubrique

extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)Lien vers cette définition

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.

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 :

    Code
    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 :

    SQL
    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 :

    Code
    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 :

    SQL
    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 :

    Code
    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 :

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

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

    SQL
    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 :

    Code
    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 :

    Code
    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 :

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

    Juste :

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

defer()Lien vers cette rubrique

defer(*fields)Lien vers cette définition

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():

Code
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).

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

Code
# 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 :

Code
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():

Code
# 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.

only()Lien vers cette rubrique

only(*fields)Lien vers cette définition

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 :

Code
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 :

Code
# 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 :

Code
# 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().

using()Lien vers cette rubrique

using(alias)Lien vers cette définition

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 :

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

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

select_for_update()Lien vers cette rubrique

select_for_update(nowait=False, skip_locked=False, of=(), no_key=False)Lien vers cette définition

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 :

Code
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.

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 :

Python console
>>> 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 :

Python console
>>> 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.

raw()Lien vers cette rubrique

raw(raw_query, params=(), translations=None, using=None)Lien vers cette définition

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.

Opérateurs renvoyant de nouveaux QuerySetLien vers cette rubrique

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

AND (&)Lien vers cette rubrique

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

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

Équivalent SQL :

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

OR (|)Lien vers cette rubrique

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

Les requêtes suivantes sont équivalentes

Code
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 :

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 (^)Lien vers cette rubrique

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

Code
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 :

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

Méthodes qui ne renvoient pas de QuerySetLien vers cette rubrique

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()Lien vers cette rubrique

get(*args, **kwargs)Lien vers cette définition
aget(*args, **kwargs)Lien vers cette définition

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

Code
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 :

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

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

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

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

Code
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

Code
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()Lien vers cette rubrique

create(**kwargs)Lien vers cette définition
acreate(**kwargs)Lien vers cette définition

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 :

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

et :

Code
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()Lien vers cette rubrique

get_or_create(defaults=None, **kwargs)Lien vers cette définition
aget_or_create(defaults=None, **kwargs)Lien vers cette définition

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éé)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 :

Code
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 :

Code
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.

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:

Code
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

Code
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 :

Code
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.

update_or_create()Lien vers cette rubrique

update_or_create(defaults=None, create_defaults=None, **kwargs)Lien vers cette définition
aupdate_or_create(defaults=None, create_defaults=None, **kwargs)Lien vers cette définition

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éé)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 :

Code
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 :

Code
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()Lien vers cette rubrique

bulk_create(objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None, unique_fields=None)Lien vers cette définition
abulk_create(objs, batch_size=None, ignore_conflicts=False, update_conflicts=False, update_fields=None, unique_fields=None)Lien vers cette définition

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 :

Python console
>>> 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

    Code
    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).

bulk_update()Lien vers cette rubrique

bulk_update(objs, fields, batch_size=None)Lien vers cette définition
abulk_update(objs, fields, batch_size=None)Lien vers cette définition

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 :

Python console
>>> 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 :

    Code
    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()Lien vers cette rubrique

count()Lien vers cette définition
acount()Lien vers cette définition

Version asynchrone: acount()

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

Exemple :

Code
# 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()Lien vers cette rubrique

in_bulk(id_list=None, *, field_name='pk')Lien vers cette définition
ain_bulk(id_list=None, *, field_name='pk')Lien vers cette définition

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 :

Python console
>>> 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.

iterator()Lien vers cette rubrique

iterator(chunk_size=None)Lien vers cette définition
aiterator(chunk_size=None)Lien vers cette définition

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é serveurLien vers cette rubrique

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é serveurLien vers cette rubrique

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()Lien vers cette rubrique

latest(*fields)Lien vers cette définition
alatest(*fields)Lien vers cette définition

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:

Code
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:

Code
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()Lien vers cette rubrique

earliest(*fields)Lien vers cette définition
aearliest(*fields)Lien vers cette définition

Version asynchrone: aearliest()

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

first()Lien vers cette rubrique

first()Lien vers cette définition
afirst()Lien vers cette définition

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 :

Code
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 :

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

last()Lien vers cette rubrique

last()Lien vers cette définition
alast()Lien vers cette définition

Version asynchrone: alast()

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

aggregate()Lien vers cette rubrique

aggregate(*args, **kwargs)Lien vers cette définition
aaggregate(*args, **kwargs)Lien vers cette définition

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 :

Python console
>>> 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 :

Python console
>>> 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()Lien vers cette rubrique

exists()Lien vers cette définition
aexists()Lien vers cette définition

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 :

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

Ce qui sera plus rapide que :

Code
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()Lien vers cette rubrique

contains(obj)Lien vers cette définition
acontains(obj)Lien vers cette définition

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 :

Code
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 :

Code
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()Lien vers cette rubrique

update(**kwargs)Lien vers cette définition
aupdate(**kwargs)Lien vers cette définition

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 :

Python console
>>> 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:

Python console
>>> 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 :

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

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

Python console
>>> 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 :

Python console
>>> 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 :

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

…faites ceci :

Code
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().

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:

Code
for e in Entry.objects.filter(pub_date__year=2010):
    e.comments_on = False
    e.save()
Jeux de requête triésLien vers cette rubrique

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

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

delete()Lien vers cette rubrique

delete()Lien vers cette définition
adelete()Lien vers cette définition

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 :

Python console
>>> 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 :

Python console
>>> 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é.

as_manager()Lien vers cette rubrique

classmethod as_manager()Lien vers cette définition

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()Lien vers cette rubrique

explain(format=None, **options)Lien vers cette définition
aexplain(format=None, **options)Lien vers cette définition

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 :

Python console
>>> 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 :

Python console
>>> 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 champsLien vers cette rubrique

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.

exactLien vers cette rubrique

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 :

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

Équivalence en SQL :

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

iexactLien vers cette rubrique

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 :

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

Équivalence en SQL :

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.

containsLien vers cette rubrique

Test d’inclusion sensible à la casse.

Exemple :

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

Équivalent SQL :

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'.

icontainsLien vers cette rubrique

Test d’inclusion insensible à la casse.

Exemple :

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

Équivalent SQL :

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

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

inLien vers cette rubrique

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 :

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

Équivalence en SQL :

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 :

Code
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 :

SQL
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) :

Code
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 :

Code
# 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)

gtLien vers cette rubrique

Plus grand que.

Exemple :

Code
Entry.objects.filter(id__gt=4)

Équivalent SQL :

SQL
SELECT ... WHERE id > 4;

gteLien vers cette rubrique

Plus grand ou égal à.

ltLien vers cette rubrique

Plus petit que.

lteLien vers cette rubrique

Plus petit ou égal à.

startswithLien vers cette rubrique

Commence par (sensible à la casse).

Exemple :

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

Équivalent SQL :

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.

istartswithLien vers cette rubrique

Commence par (non sensible à la casse).

Exemple :

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

Équivalent SQL :

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

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

endswithLien vers cette rubrique

Se termine par (sensible à la casse).

Exemple :

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

Équivalent SQL :

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

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

iendswithLien vers cette rubrique

Se termine par (non sensible à la casse).

Exemple :

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

Équivalent SQL :

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

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

rangeLien vers cette rubrique

Test d’intervalle (inclusif).

Exemple :

Code
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 :

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.

dateLien vers cette rubrique

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 :

Code
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.

yearLien vers cette rubrique

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 :

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

Équivalent SQL :

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_yearLien vers cette rubrique

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 :

Code
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.

monthLien vers cette rubrique

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 :

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

Équivalent SQL :

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.

dayLien vers cette rubrique

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 :

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

Équivalent SQL :

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.

weekLien vers cette rubrique

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 :

Code
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_dayLien vers cette rubrique

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 :

Code
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_dayLien vers cette rubrique

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 :

Code
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.

quarterLien vers cette rubrique

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)

Code
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.

timeLien vers cette rubrique

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 :

Code
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.

hourLien vers cette rubrique

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 :

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

Équivalent SQL :

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.

minuteLien vers cette rubrique

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 :

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

Équivalent SQL :

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.

secondLien vers cette rubrique

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 :

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

Équivalent SQL :

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.

isnullLien vers cette rubrique

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

Exemple :

Code
Entry.objects.filter(pub_date__isnull=True)

Équivalent SQL :

SQL
SELECT ... WHERE pub_date IS NULL;

regexLien vers cette rubrique

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 :

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

Équivalence en SQL :

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.

iregexLien vers cette rubrique

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

Exemple :

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

Équivalence en SQL :

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égationLien vers cette rubrique

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.

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

expressionsLien vers cette rubrique

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

output_fieldLien vers cette rubrique

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

filterLien vers cette rubrique

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.

defaultLien vers cette rubrique

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.

**extraLien vers cette rubrique

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

AnyValueLien vers cette rubrique

class AnyValue(expression, output_field=None, filter=None, default=None, **extra)Lien vers cette définition

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 :

Python console
>>> # 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+.

AvgLien vers cette rubrique

class Avg(expression, output_field=None, distinct=False, filter=None, default=None, **extra)Lien vers cette définition

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.

distinctLien vers cette définition

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.

BitAndLien vers cette rubrique

class BitAnd(expression, filter=None, default=None, **extra)Lien vers cette définition

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.

BitOrLien vers cette rubrique

class BitOr(expression, filter=None, default=None, **extra)Lien vers cette définition

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.

BitXorLien vers cette rubrique

class BitXor(expression, filter=None, default=None, **extra)Lien vers cette définition

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.

CountLien vers cette rubrique

class Count(expression, distinct=False, filter=None, **extra)Lien vers cette définition

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

distinctLien vers cette définition

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.

MaxLien vers cette rubrique

class Max(expression, output_field=None, filter=None, default=None, **extra)Lien vers cette définition

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.

MinLien vers cette rubrique

class Min(expression, output_field=None, filter=None, default=None, **extra)Lien vers cette définition

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.

StdDevLien vers cette rubrique

class StdDev(expression, output_field=None, sample=False, filter=None, default=None, **extra)Lien vers cette définition

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.

sampleLien vers cette définition

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.

SumLien vers cette rubrique

class Sum(expression, output_field=None, distinct=False, filter=None, default=None, **extra)Lien vers cette définition

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.

distinctLien vers cette définition

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`.

VarianceLien vers cette rubrique

class Variance(expression, output_field=None, sample=False, filter=None, default=None, **extra)Lien vers cette définition

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.

sampleLien vers cette définition

Facultatif. Par défaut, Variance renvoie la variance de population. Cependant, si sample=True, la valeur renvoyée sera la variance d’échantillon.

StringAggLien vers cette rubrique

class StringAgg(expression, delimiter, output_field=None, distinct=False, filter=None, order_by=None, default=None, **extra)Lien vers cette définition

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.

delimiterLien vers cette définition

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.)