# Documentation Django 5.2.8

# Fonctions de base de données

The classes documented below provide a way for users to use functions provided by the underlying database as annotations, aggregations, or filters in Django. Functions are also expressions, so they can be used and combined with other expressions like aggregate functions.

Nous allons utiliser le modèle suivant dans les exemples de chaque fonction :

    class Author(models.Model):
        name = models.CharField(max_length=50)
        age = models.PositiveIntegerField(null=True, blank=True)
        alias = models.CharField(max_length=50, null=True, blank=True)
        goes_by = models.CharField(max_length=50, null=True, blank=True)

Nous ne recommandons généralement pas de définir `null=True` pour les champs `CharField` car cela permet au champ de posséder deux valeurs « vides » différentes, mais nous l’utilisons ici pour l’exemple `Coalesce` ci-dessous.

## Fonctions de comparaison et de conversion

### `Cast`

class Cast(expression, output_field)

Force le type de résultat de `expression` à celui de `output_field`.

Exemple d’utilisation :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Cast
    >>> Author.objects.create(age=25, name="Margaret Smith")
    >>> author = Author.objects.annotate(
    ...     age_as_float=Cast("age", output_field=FloatField()),
    ... ).get()
    >>> print(author.age_as_float)
    25.0

### `Coalesce`

class Coalesce(*expressions, **extra)

Accepte une liste d’au moins deux noms de champ ou expressions et renvoie la première valeur non nulle (notez qu’une chaîne vide n’est pas considérée comme une valeur nulle). Chaque paramètre doit être d’un type similaire ; si vous mélangez des textes et des nombres, la base de données produira une erreur.

Exemples d’utilisation :

    >>> # Get a screen name from least to most public
    >>> from django.db.models import Sum
    >>> from django.db.models.functions import Coalesce
    >>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
    >>> author = Author.objects.annotate(screen_name=Coalesce("alias", "goes_by", "name")).get()
    >>> print(author.screen_name)
    Maggie

    >>> # Prevent an aggregate Sum() from returning None
    >>> # The aggregate default argument uses Coalesce() under the hood.
    >>> aggregated = Author.objects.aggregate(
    ...     combined_age=Sum("age"),
    ...     combined_age_default=Sum("age", default=0),
    ...     combined_age_coalesce=Coalesce(Sum("age"), 0),
    ... )
    >>> print(aggregated["combined_age"])
    None
    >>> print(aggregated["combined_age_default"])
    0
    >>> print(aggregated["combined_age_coalesce"])
    0

Avertissement

Avec MySQL, il est possible qu’une valeur Python transmise à `Coalesce` soit convertie en un type incorrect, sauf dans le cas où le bon type de base de données est explicitement forcé :

    >>> from django.db.models import DateTimeField
    >>> from django.db.models.functions import Cast, Coalesce
    >>> from django.utils import timezone
    >>> now = timezone.now()
    >>> Coalesce("updated", Cast(now, DateTimeField()))

### `Collate`

class Collate(expression, collation)

Accepte une expression et un nom de collation à utiliser pour la requête.

Par exemple, pour filtrer sans tenir compte de la casse avec SQLite :

    >>> Author.objects.filter(name=Collate(Value("john"), "nocase"))
    <QuerySet [<Author: John>, <Author: john>]>

C’est aussi utilisable pour le tri, par exemple avec PostgreSQL :

    >>> Author.objects.order_by(Collate("name", "et-x-icu"))
    <QuerySet [<Author: Ursula>, <Author: Veronika>, <Author: Ülle>]>

### `Greatest`

class Greatest(*expressions, **extra)

Accepte une liste d’au moins deux noms de champ ou expressions et renvoie la plus grande valeur. Chaque paramètre doit être d’un type similaire ; si vous mélangez des textes et des nombres, la base de données produira une erreur.

Exemple d’utilisation :

    class Blog(models.Model):
        body = models.TextField()
        modified = models.DateTimeField(auto_now=True)

    class Comment(models.Model):
        body = models.TextField()
        modified = models.DateTimeField(auto_now=True)
        blog = models.ForeignKey(Blog, on_delete=models.CASCADE)

    >>> from django.db.models.functions import Greatest
    >>> blog = Blog.objects.create(body="Greatest is the best.")
    >>> comment = Comment.objects.create(body="No, Least is better.", blog=blog)
    >>> comments = Comment.objects.annotate(last_updated=Greatest("modified", "blog__modified"))
    >>> annotated_comment = comments.get()

`annotated_comment.last_updated` sera la valeur la plus récente entre `blog.modified` et `comment.modified`.

Avertissement

Le comportement de `Greatest` varie entre les bases de données lorsqu’une ou plusieurs des expressions ont la valeur `null`:

- PostgreSQL : `Greatest` renvoie l’expression non nulle la plus grande, ou `null` si toutes les expressions valent `null`.

- SQLite, Oracle et MySQL : si l’une des expressions vaut `null`, `Greatest` renvoie `null`.

Le comportement de PostgreSQL peut être émulé à l’aide de `Coalesce` si vous avez une valeur minimum adéquate à fournir comme valeur par défaut.

### `Least`

class Least(*expressions, **extra)

Accepte une liste d’au moins deux noms de champ ou expressions et renvoie la plus petite valeur. Chaque paramètre doit être d’un type similaire ; si vous mélangez des textes et des nombres, la base de données produira une erreur.

Avertissement

Le comportement de `Least` varie entre les bases de données lorsqu’une ou plusieurs des expressions ont la valeur `null`:

- PostgreSQL : `Least` renvoie l’expression non nulle la plus petite, ou `null` si toutes les expressions valent `null`.

- SQLite, Oracle et MySQL : si l’une des expressions vaut `null`, `Least` renvoie `null`.

Le comportement de PostgreSQL peut être émulé à l’aide de `Coalesce` si vous avez une valeur maximum adéquate à fournir comme valeur par défaut.

### `NullIf`

class NullIf(expression1, expression2)

Accepte deux expressions et renvoie `None` si elles sont égales, sinon renvoie `expression1`.

Avertissement pour Oracle

En raison d’une convention Oracle, cette fonction renvoie la chaîne vide au lieu de `None` lorsque les expressions sont de type `CharField`.

La transmission de `Value(None)` à `expression1` est interdite avec Oracle car cette base de données n’accepte pas `NULL` comme premier paramètre.

## Fonctions de date

Nous allons utiliser le modèle suivant dans les exemples de chaque fonction :

    class Experiment(models.Model):
        start_datetime = models.DateTimeField()
        start_date = models.DateField(null=True, blank=True)
        start_time = models.TimeField(null=True, blank=True)
        end_datetime = models.DateTimeField(null=True, blank=True)
        end_date = models.DateField(null=True, blank=True)
        end_time = models.TimeField(null=True, blank=True)

### `Extract`

class Extract(expression, lookup_name=None, tzinfo=None, **extra)

Extrait un composant de date sous forme de nombre.

Accepte une `expression` représentant un champ `DateField`, `DateTimeField`, `TimeField` ou `DurationField` ainsi qu’un nom d’expression `lookup_name`, et renvoie la partie de date référencée par `lookup_name` sous forme de champ `IntegerField`. Django utilise habituellement la fonction d’extraction des bases de données, il est donc possible d’utiliser n’importe quel nom `lookup_name` pris en charge par la base de données en cours. Il est possible de passer aussi une sous-classe de `tzinfo`, habituellement fournie par `zoneinfo`, pour extraire une valeur dans un fuseau horaire spécifique.

Étant donnée la date/heure `2015-06-15 23:30:01.000321+00:00`, les valeurs `lookup_name` possibles renvoient :

- « year » (année) : 2015

- « iso_year » (année ISO) : 2015

- « quarter »: 2

- « month » (mois) : 6

- « day » (jour) : 15

- « week »: 25

- « week_day » (jour de semaine) : 2

- « iso_week_day »: 1

- « hour » (heure) : 23

- « minute »: 30

- « second »: 1

Si un fuseau horaire différent comme `Australia/Melbourne` est actif dans Django, la date/heure est convertie dans le fuseau avant que la valeur soit extraite. Le décalage horaire de Melbourne dans la date d’exemple ci-dessus est +10:00. Les valeurs renvoyées lorsque ce fuseau est actif seront les mêmes que ci-dessus, à l’exception de :

- « day »: 16

- « week_day »: 3

- « iso_week_day »: 2

- « hour »: 9

Valeurs `week_day`

L’extraction `week_day` est calculée différemment de la plupart des bases de données et des fonctions Python standards. Cette fonction renvoie `1` pour dimanche, `2` pour lundi, jusqu’à `7` pour samedi.

Le calcul équivalent en Python est :

    >>> from datetime import datetime
    >>> dt = datetime(2015, 6, 15)
    >>> (dt.isoweekday() % 7) + 1
    2

Valeurs `week`

L’expression de recherche `week` est calculée sur la base du standard ISO-8601, c’est-à-dire qu’une semaine commence un lundi. La première semaine d’une année est celle qui contient le premier jeudi de l’année, c’est-à-dire que la première semaine à sa majorité (4 ou plus) de jours dans l’année. La valeur renvoyée se situe dans l’intervalle 1 à 52 ou 53.

Chaque valeur `lookup_name` ci-dessus possède une sous-classe de `Extract` correspondante (énumérées ci-dessous) qui devrait être utilisée au lieu de l’équivalent plus bavard, c’est-à-dire `ExtractYear(...)` au lieu de `Extract(..., lookup_name='year')`.

Exemple d’utilisation :

    >>> from datetime import datetime
    >>> from django.db.models.functions import Extract
    >>> start = datetime(2015, 6, 15)
    >>> end = datetime(2015, 7, 2)
    >>> Experiment.objects.create(
    ...     start_datetime=start, start_date=start.date(), end_datetime=end, end_date=end.date()
    ... )
    >>> # Add the experiment start year as a field in the QuerySet.
    >>> experiment = Experiment.objects.annotate(
    ...     start_year=Extract("start_datetime", "year")
    ... ).get()
    >>> experiment.start_year
    2015
    >>> # How many experiments completed in the same year in which they started?
    >>> Experiment.objects.filter(start_datetime__year=Extract("end_datetime", "year")).count()
    1

#### Extractions `DateField`

class ExtractYear(expression, tzinfo=None, **extra)
  lookup_name = 'year'

class ExtractIsoYear(expression, tzinfo=None, **extra)

  Renvoie l’année avec numéro de semaine selon ISO-8601.

  lookup_name = 'iso_year'

class ExtractMonth(expression, tzinfo=None, **extra)
  lookup_name = 'month'

class ExtractDay(expression, tzinfo=None, **extra)
  lookup_name = 'day'

class ExtractWeekDay(expression, tzinfo=None, **extra)
  lookup_name = 'week_day'

class ExtractIsoWeekDay(expression, tzinfo=None, **extra)

  Renvoie le jour de la semaine ISO-8601, le jour 1 étant un lundi et le jour 7 un dimanche.

  lookup_name = 'iso_week_day'

class ExtractWeek(expression, tzinfo=None, **extra)
  lookup_name = 'week'

class ExtractQuarter(expression, tzinfo=None, **extra)
  lookup_name = 'quarter'

Il s’agit d’équivalents logiques à `Extract('champ_date', lookup_name)`. Chaque classe est aussi une classe `Transform` inscrite pour les champs `DateField` et `DateTimeField` comme `__(lookup_name)`, par ex. `__year`.

Comme les champs `DateField` n’ont pas de composant d’heure, seules les sous-classes de `Extract` qui s’appliquent aux parties de date peuvent être utilisées avec `DateField`:

    >>> from datetime import UTC, datetime
    >>> from django.db.models.functions import (
    ...     ExtractDay,
    ...     ExtractMonth,
    ...     ExtractQuarter,
    ...     ExtractWeek,
    ...     ExtractIsoWeekDay,
    ...     ExtractWeekDay,
    ...     ExtractIsoYear,
    ...     ExtractYear,
    ... )
    >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=UTC)
    >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=UTC)
    >>> Experiment.objects.create(
    ...     start_datetime=start_2015,
    ...     start_date=start_2015.date(),
    ...     end_datetime=end_2015,
    ...     end_date=end_2015.date(),
    ... )
    >>> Experiment.objects.annotate(
    ...     year=ExtractYear("start_date"),
    ...     isoyear=ExtractIsoYear("start_date"),
    ...     quarter=ExtractQuarter("start_date"),
    ...     month=ExtractMonth("start_date"),
    ...     week=ExtractWeek("start_date"),
    ...     day=ExtractDay("start_date"),
    ...     weekday=ExtractWeekDay("start_date"),
    ...     isoweekday=ExtractIsoWeekDay("start_date"),
    ... ).values(
    ...     "year",
    ...     "isoyear",
    ...     "quarter",
    ...     "month",
    ...     "week",
    ...     "day",
    ...     "weekday",
    ...     "isoweekday",
    ... ).get(
    ...     end_date__year=ExtractYear("start_date")
    ... )
    {'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
     'day': 15, 'weekday': 2, 'isoweekday': 1}

#### Extractions `DateTimeField`

En plus de ce qui suit, toutes les extractions pour `DateField` énumérées ci-dessus peuvent aussi être utilisées pour `DateTimeField`.

class ExtractHour(expression, tzinfo=None, **extra)
  lookup_name = 'hour'

class ExtractMinute(expression, tzinfo=None, **extra)
  lookup_name = 'minute'

class ExtractSecond(expression, tzinfo=None, **extra)
  lookup_name = 'second'

Il s’agit d’équivalents logiques à `Extract('champ_datetime', lookup_name)`. Chaque classe est aussi une classe `Transform` inscrite pour le champ `DateTimeField` comme `__(lookup_name)`, par ex. `__minute`.

Exemples `DateTimeField`:

    >>> from datetime import UTC, datetime
    >>> from django.db.models.functions import (
    ...     ExtractDay,
    ...     ExtractHour,
    ...     ExtractMinute,
    ...     ExtractMonth,
    ...     ExtractQuarter,
    ...     ExtractSecond,
    ...     ExtractWeek,
    ...     ExtractIsoWeekDay,
    ...     ExtractWeekDay,
    ...     ExtractIsoYear,
    ...     ExtractYear,
    ... )
    >>> start_2015 = datetime(2015, 6, 15, 23, 30, 1, tzinfo=UTC)
    >>> end_2015 = datetime(2015, 6, 16, 13, 11, 27, tzinfo=UTC)
    >>> Experiment.objects.create(
    ...     start_datetime=start_2015,
    ...     start_date=start_2015.date(),
    ...     end_datetime=end_2015,
    ...     end_date=end_2015.date(),
    ... )
    >>> Experiment.objects.annotate(
    ...     year=ExtractYear("start_datetime"),
    ...     isoyear=ExtractIsoYear("start_datetime"),
    ...     quarter=ExtractQuarter("start_datetime"),
    ...     month=ExtractMonth("start_datetime"),
    ...     week=ExtractWeek("start_datetime"),
    ...     day=ExtractDay("start_datetime"),
    ...     weekday=ExtractWeekDay("start_datetime"),
    ...     isoweekday=ExtractIsoWeekDay("start_datetime"),
    ...     hour=ExtractHour("start_datetime"),
    ...     minute=ExtractMinute("start_datetime"),
    ...     second=ExtractSecond("start_datetime"),
    ... ).values(
    ...     "year",
    ...     "isoyear",
    ...     "month",
    ...     "week",
    ...     "day",
    ...     "weekday",
    ...     "isoweekday",
    ...     "hour",
    ...     "minute",
    ...     "second",
    ... ).get(
    ...     end_datetime__year=ExtractYear("start_datetime")
    ... )
    {'year': 2015, 'isoyear': 2015, 'quarter': 2, 'month': 6, 'week': 25,
     'day': 15, 'weekday': 2, 'isoweekday': 1, 'hour': 23, 'minute': 30,
     'second': 1}

Lorsque `USE_TZ` vaut `True`, les dates/heures sont stockées en UTC dans la base de données. Si un autre fuseau horaire est actif dans Django, la date/heure est convertie dans ce fuseau avant que la valeur soit extraite. L’exemple ci-dessous convertit dans le fuseau horaire de Melbourne (UTC +10:00), ce qui modifie les valeurs du jour, du jour de la semaine et de l’heure qui sont renvoyées :

    >>> from django.utils import timezone
    >>> import zoneinfo
    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")  # UTC+10:00
    >>> with timezone.override(melb):
    ...     Experiment.objects.annotate(
    ...         day=ExtractDay("start_datetime"),
    ...         weekday=ExtractWeekDay("start_datetime"),
    ...         isoweekday=ExtractIsoWeekDay("start_datetime"),
    ...         hour=ExtractHour("start_datetime"),
    ...     ).values("day", "weekday", "isoweekday", "hour").get(
    ...         end_datetime__year=ExtractYear("start_datetime"),
    ...     )
    ...
    {'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}

Le passage explicite du fuseau horaire à la fonction `Extract` fonctionne de la même manière et prend la priorité sur le fuseau horaire actif :

    >>> import zoneinfo
    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
    >>> Experiment.objects.annotate(
    ...     day=ExtractDay("start_datetime", tzinfo=melb),
    ...     weekday=ExtractWeekDay("start_datetime", tzinfo=melb),
    ...     isoweekday=ExtractIsoWeekDay("start_datetime", tzinfo=melb),
    ...     hour=ExtractHour("start_datetime", tzinfo=melb),
    ... ).values("day", "weekday", "isoweekday", "hour").get(
    ...     end_datetime__year=ExtractYear("start_datetime"),
    ... )
    {'day': 16, 'weekday': 3, 'isoweekday': 2, 'hour': 9}

### `Now`

class Now

Renvoie la date et l’heure courante du serveur de base de données au moment où la requête est exécutée, typiquement en utilisant le code SQL `CURRENT_TIMESTAMP`.

Exemple d’utilisation :

    >>> from django.db.models.functions import Now
    >>> Article.objects.filter(published__lte=Now())
    <QuerySet [<Article: How to Django>]>

Considérations sur PostgreSQL

Avec PostgreSQL, l’instruction `CURRENT_TIMESTAMP` renvoie l’heure du début de la transaction actuelle. Par conséquent, pour garantir la compatibilité entre bases de données, `Now()` utilise `STATEMENT_TIMESTAMP` à la place. Si vous avez besoin de l’horodatage de la transaction, utilisez `django.contrib.postgres.functions.TransactionNow`.

Oracle

Avec Oracle, l’instruction SQL `LOCALTIMESTAMP` est utilisée pour éviter les problèmes de forçage de `CURRENT_TIMESTAMP` vers `DateTimeField`.

### `Trunc`

class Trunc(expression, kind, output_field=None, tzinfo=None, **extra)

Tronque une date jusqu’à un composant significatif.

Lorsque vous ne voulez que savoir si quelque chose s’est produit durant une année, une heure ou un jour particulier, mais pas à quelle seconde, `Trunc` (et ses sous-classes) peut être utile pour filtrer ou agréger vos données. Par exemple, vous pouvez utiliser `Trunc` pour calculer le nombre de ventes par jour.

`Trunc` accepte une seule `expression`, représentant un champ `DateField`, `TimeField` ou `DateTimeField`, une variable `kind` représentant une partie de date ou d’heure et un champ `output_field` qui vaut `DateTimeField()`, `TimeField()` ou `DateField()`. Elle renvoie une date, une heure ou une date/heure en fonction de `output_field`, avec les champs jusqu’à `kind` définis à leur valeur minimale. Si `output_field` est omis, la valeur par défaut sera le type `output_field` de `expression`. Il est possible de passer aussi une sous-classe de `tzinfo`, habituellement fournie par `zoneinfo`, pour tronquer une valeur dans un fuseau horaire spécifique.

Étant donnée la date/heure `2015-06-15 14:30:50.000321+00:00`, les valeurs `kind` possibles renvoient :

- « year »: 2015-01-01 00:00:00+00:00

- « quarter »: 2015-04-01 00:00:00+00:00

- « month »: 2015-06-01 00:00:00+00:00

- « week »: 2015-06-15 00:00:00+00:00

- « day »: 2015-06-15 00:00:00+00:00

- « hour »: 2015-06-15 14:00:00+00:00

- « minute »: 2015-06-15 14:30:00+00:00

- « second »: 2015-06-15 14:30:50+00:00

Si un fuseau horaire différent comme `Australia/Melbourne` est actif dans Django, la date/heure est convertie dans le nouveau fuseau avant que la valeur soit tronquée. Le décalage horaire de Melbourne dans la date d’exemple ci-dessus est +10:00. Les valeurs renvoyées lorsque ce fuseau est actif seront :

- « year »: 2015-01-01 00:00:00+11:00

- « quarter »: 2015-04-01 00:00:00+10:00

- « month »: 2015-06-01 00:00:00+10:00

- « week »: 2015-06-16 00:00:00+10:00

- « day »: 2015-06-16 00:00:00+10:00

- « hour »: 2015-06-16 00:00:00+10:00

- « minute »: 2015-06-16 00:30:00+10:00

- « second »: 2015-06-16 00:30:50+10:00

L’année présente un décalage de +11:00 parce que le résultat traverse un passage à l’heure d’été.

Chaque valeur `kind` ci-dessus possède une sous-classe de `Trunc` correspondante (énumérées ci-dessous) qui devrait être utilisée au lieu de l’équivalent plus bavard, c’est-à-dire `TruncYear(...)` au lieu de `Trunc(..., kind='year')`.

Les sous-classes sont toutes définies comme des transformations, mais elles ne sont inscrites pour aucun champ, car les noms de requête sont déjà réservés par les sous-classes de `Extract`.

Exemple d’utilisation :

    >>> from datetime import datetime
    >>> from django.db.models import Count, DateTimeField
    >>> from django.db.models.functions import Trunc
    >>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 30, 50, 321))
    >>> Experiment.objects.create(start_datetime=datetime(2015, 6, 15, 14, 40, 2, 123))
    >>> Experiment.objects.create(start_datetime=datetime(2015, 12, 25, 10, 5, 27, 999))
    >>> experiments_per_day = (
    ...     Experiment.objects.annotate(
    ...         start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
    ...     )
    ...     .values("start_day")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_day:
    ...     print(exp["start_day"], exp["experiments"])
    ...
    2015-06-15 00:00:00 2
    2015-12-25 00:00:00 1
    >>> experiments = Experiment.objects.annotate(
    ...     start_day=Trunc("start_datetime", "day", output_field=DateTimeField())
    ... ).filter(start_day=datetime(2015, 6, 15))
    >>> for exp in experiments:
    ...     print(exp.start_datetime)
    ...
    2015-06-15 14:30:50.000321
    2015-06-15 14:40:02.000123

#### Troncature de `DateField`

class TruncYear(expression, output_field=None, tzinfo=None, **extra)
  kind = 'year'

class TruncMonth(expression, output_field=None, tzinfo=None, **extra)
  kind = 'month'

class TruncWeek(expression, output_field=None, tzinfo=None, **extra)

  Tronque à minuit le lundi de la semaine.

  kind = 'week'

class TruncQuarter(expression, output_field=None, tzinfo=None, **extra)
  kind = 'quarter'

Ce sont des équivalences logiques à `Trunc('champ_date', kind)`. Elles tronquent toutes les parties de la date jusqu’à `kind`, ce qui permet de grouper ou de filtrer des dates avec une plus faible précision. `expression` peut avoir une valeur `output_field` de `DateField` ou de `DateTimeField`.

Comme les champs `DateField` n’ont pas de composant d’heure, seules les sous-classes de `Trunc` qui s’appliquent aux parties de date peuvent être utilisées avec `DateField`:

    >>> from datetime import UTC, datetime
    >>> from django.db.models import Count
    >>> from django.db.models.functions import TruncMonth, TruncYear
    >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=UTC)
    >>> start2 = datetime(2015, 6, 15, 14, 40, 2, 123, tzinfo=UTC)
    >>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=UTC)
    >>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
    >>> Experiment.objects.create(start_datetime=start2, start_date=start2.date())
    >>> Experiment.objects.create(start_datetime=start3, start_date=start3.date())
    >>> experiments_per_year = (
    ...     Experiment.objects.annotate(year=TruncYear("start_date"))
    ...     .values("year")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_year:
    ...     print(exp["year"], exp["experiments"])
    ...
    2014-01-01 1
    2015-01-01 2

    >>> import zoneinfo
    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
    >>> experiments_per_month = (
    ...     Experiment.objects.annotate(month=TruncMonth("start_datetime", tzinfo=melb))
    ...     .values("month")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_month:
    ...     print(exp["month"], exp["experiments"])
    ...
    2015-06-01 00:00:00+10:00 1
    2016-01-01 00:00:00+11:00 1
    2014-06-01 00:00:00+10:00 1

#### Troncature de `DateTimeField`

class TruncDate(expression, tzinfo=None, **extra)
  lookup_name = 'date'
  output_field = DateField()

`TruncDate` force le type de `expression` à une date plutôt que d’utiliser l’instruction SQL de troncature. Elle est aussi inscrite comme transformation pour `DateTimeField` sous la forme `__date`.

class TruncTime(expression, tzinfo=None, **extra)
  lookup_name = 'time'
  output_field = TimeField()

`TruncTime` force le type de `expression` à une heure plutôt que d’utiliser l’instruction SQL de troncature. Elle est aussi inscrite comme transformation pour `DateTimeField` sous la forme `__time`.

class TruncDay(expression, output_field=None, tzinfo=None, **extra)
  kind = 'day'

class TruncHour(expression, output_field=None, tzinfo=None, **extra)
  kind = 'hour'

class TruncMinute(expression, output_field=None, tzinfo=None, **extra)
  kind = 'minute'

class TruncSecond(expression, output_field=None, tzinfo=None, **extra)
  kind = 'second'

Ce sont des équivalences logiques à `Trunc('champ_dateheure', kind)`. Elles tronquent toutes les parties de la date jusqu’à `kind`, ce qui permet de grouper ou de filtrer des dates/heures avec une plus faible précision. `expression` doit avoir une valeur `output_field` de `DateTimeField`.

Exemple d’utilisation :

    >>> from datetime import UTC, date, datetime
    >>> from django.db.models import Count
    >>> from django.db.models.functions import (
    ...     TruncDate,
    ...     TruncDay,
    ...     TruncHour,
    ...     TruncMinute,
    ...     TruncSecond,
    ... )
    >>> import zoneinfo
    >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=UTC)
    >>> Experiment.objects.create(start_datetime=start1, start_date=start1.date())
    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
    >>> Experiment.objects.annotate(
    ...     date=TruncDate("start_datetime"),
    ...     day=TruncDay("start_datetime", tzinfo=melb),
    ...     hour=TruncHour("start_datetime", tzinfo=melb),
    ...     minute=TruncMinute("start_datetime"),
    ...     second=TruncSecond("start_datetime"),
    ... ).values("date", "day", "hour", "minute", "second").get()
    {'date': datetime.date(2014, 6, 15),
     'day': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
     'hour': datetime.datetime(2014, 6, 16, 0, 0, tzinfo=zoneinfo.ZoneInfo('Australia/Melbourne')),
     'minute': 'minute': datetime.datetime(2014, 6, 15, 14, 30, tzinfo=UTC),
     'second': datetime.datetime(2014, 6, 15, 14, 30, 50, tzinfo=UTC)
    }

#### Troncature de `TimeField`

class TruncHour(expression, output_field=None, tzinfo=None, **extra)
  kind = 'hour'

class TruncMinute(expression, output_field=None, tzinfo=None, **extra)
  kind = 'minute'

class TruncSecond(expression, output_field=None, tzinfo=None, **extra)
  kind = 'second'

Ce sont des équivalences logiques à `Trunc('champ_heure', kind)`. Elles tronquent toutes les parties de l’heure jusqu’à `kind`, ce qui permet de grouper ou de filtrer des heures avec une plus faible précision. `expression` peut avoir une valeur `output_field` de `TimeField` ou de `DateTimeField`.

Comme les champs `TimeField` n’ont pas de composant de date, seules les sous-classes de `Trunc` qui s’appliquent aux parties d’heure peuvent être utilisées avec `TimeField`:

    >>> from datetime import UTC, datetime
    >>> from django.db.models import Count, TimeField
    >>> from django.db.models.functions import TruncHour
    >>> start1 = datetime(2014, 6, 15, 14, 30, 50, 321, tzinfo=UTC)
    >>> start2 = datetime(2014, 6, 15, 14, 40, 2, 123, tzinfo=UTC)
    >>> start3 = datetime(2015, 12, 31, 17, 5, 27, 999, tzinfo=UTC)
    >>> Experiment.objects.create(start_datetime=start1, start_time=start1.time())
    >>> Experiment.objects.create(start_datetime=start2, start_time=start2.time())
    >>> Experiment.objects.create(start_datetime=start3, start_time=start3.time())
    >>> experiments_per_hour = (
    ...     Experiment.objects.annotate(
    ...         hour=TruncHour("start_datetime", output_field=TimeField()),
    ...     )
    ...     .values("hour")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_hour:
    ...     print(exp["hour"], exp["experiments"])
    ...
    14:00:00 2
    17:00:00 1

    >>> import zoneinfo
    >>> melb = zoneinfo.ZoneInfo("Australia/Melbourne")
    >>> experiments_per_hour = (
    ...     Experiment.objects.annotate(
    ...         hour=TruncHour("start_datetime", tzinfo=melb),
    ...     )
    ...     .values("hour")
    ...     .annotate(experiments=Count("id"))
    ... )
    >>> for exp in experiments_per_hour:
    ...     print(exp["hour"], exp["experiments"])
    ...
    2014-06-16 00:00:00+10:00 2
    2016-01-01 04:00:00+11:00 1

## Fonctions JSON

### `JSONArray`

New in Django 5.2.

class JSONArray(*expressions)

Accepte une liste de noms de champs ou d’expressions et renvoie un tableau JSON contenant ces valeurs.

Exemple d’utilisation :

    >>> from django.db.models import F
    >>> from django.db.models.functions import JSONArray, Lower
    >>> Author.objects.create(name="Margaret Smith", alias="msmith", age=25)
    >>> author = Author.objects.annotate(
    ...     json_array=JSONArray(
    ...         Lower("name"),
    ...         "alias",
    ...         F("age") * 2,
    ...     )
    ... ).get()
    >>> author.json_array
    ['margaret smith', 'msmith', 50]

### `JSONObject`

class JSONObject(**fields)

Accepte une liste de paires clé-valeur et renvoie un objet JSON contenant ces paires.

Exemple d’utilisation :

    >>> from django.db.models import F
    >>> from django.db.models.functions import JSONObject, Lower
    >>> Author.objects.create(name="Margaret Smith", alias="msmith", age=25)
    >>> author = Author.objects.annotate(
    ...     json_object=JSONObject(
    ...         name=Lower("name"),
    ...         alias="alias",
    ...         age=F("age") * 2,
    ...     )
    ... ).get()
    >>> author.json_object
    {'name': 'margaret smith', 'alias': 'msmith', 'age': 50}

## Fonctions mathématiques

Nous allons utiliser le modèle suivant dans les exemples de fonction mathématique qui suivront :

    class Vector(models.Model):
        x = models.FloatField()
        y = models.FloatField()

### `Abs`

class Abs(expression, **extra)

Renvoie la valeur absolue d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Abs
    >>> Vector.objects.create(x=-0.5, y=1.1)
    >>> vector = Vector.objects.annotate(x_abs=Abs("x"), y_abs=Abs("y")).get()
    >>> vector.x_abs, vector.y_abs
    (0.5, 1.1)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Abs
    >>> FloatField.register_lookup(Abs)
    >>> # Get vectors inside the unit cube
    >>> vectors = Vector.objects.filter(x__abs__lt=1, y__abs__lt=1)

### `ACos`

class ACos(expression, **extra)

Renvoie l’arccosinus d’un champ ou d’une expression numérique. La valeur de l’expression doit se situer dans l’intervalle -1 à 1.

Exemple d’utilisation :

    >>> from django.db.models.functions import ACos
    >>> Vector.objects.create(x=0.5, y=-0.9)
    >>> vector = Vector.objects.annotate(x_acos=ACos("x"), y_acos=ACos("y")).get()
    >>> vector.x_acos, vector.y_acos
    (1.0471975511965979, 2.6905658417935308)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import ACos
    >>> FloatField.register_lookup(ACos)
    >>> # Get vectors whose arccosine is less than 1
    >>> vectors = Vector.objects.filter(x__acos__lt=1, y__acos__lt=1)

### `ASin`

class ASin(expression, **extra)

Renvoie l’arcsinus d’un champ ou d’une expression numérique. La valeur de l’expression doit se situer dans l’intervalle -1 à 1.

Exemple d’utilisation :

    >>> from django.db.models.functions import ASin
    >>> Vector.objects.create(x=0, y=1)
    >>> vector = Vector.objects.annotate(x_asin=ASin("x"), y_asin=ASin("y")).get()
    >>> vector.x_asin, vector.y_asin
    (0.0, 1.5707963267948966)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import ASin
    >>> FloatField.register_lookup(ASin)
    >>> # Get vectors whose arcsine is less than 1
    >>> vectors = Vector.objects.filter(x__asin__lt=1, y__asin__lt=1)

### `ATan`

class ATan(expression, **extra)

Renvoie l’arctangente d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import ATan
    >>> Vector.objects.create(x=3.12, y=6.987)
    >>> vector = Vector.objects.annotate(x_atan=ATan("x"), y_atan=ATan("y")).get()
    >>> vector.x_atan, vector.y_atan
    (1.2606282660069106, 1.428638798133829)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import ATan
    >>> FloatField.register_lookup(ATan)
    >>> # Get vectors whose arctangent is less than 2
    >>> vectors = Vector.objects.filter(x__atan__lt=2, y__atan__lt=2)

### `ATan2`

class ATan2(expression1, expression2, **extra)

Renvoie l’arctangente de `expression1 / expression2`.

Exemple d’utilisation :

    >>> from django.db.models.functions import ATan2
    >>> Vector.objects.create(x=2.5, y=1.9)
    >>> vector = Vector.objects.annotate(atan2=ATan2("x", "y")).get()
    >>> vector.atan2
    0.9209258773829491

### `Ceil`

class Ceil(expression, **extra)

Renvoie le plus petit nombre entier plus grand ou égal au champ ou à l’expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Ceil
    >>> Vector.objects.create(x=3.12, y=7.0)
    >>> vector = Vector.objects.annotate(x_ceil=Ceil("x"), y_ceil=Ceil("y")).get()
    >>> vector.x_ceil, vector.y_ceil
    (4.0, 7.0)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Ceil
    >>> FloatField.register_lookup(Ceil)
    >>> # Get vectors whose ceil is less than 10
    >>> vectors = Vector.objects.filter(x__ceil__lt=10, y__ceil__lt=10)

### `Cos`

class Cos(expression, **extra)

Renvoie le cosinus d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Cos
    >>> Vector.objects.create(x=-8.0, y=3.1415926)
    >>> vector = Vector.objects.annotate(x_cos=Cos("x"), y_cos=Cos("y")).get()
    >>> vector.x_cos, vector.y_cos
    (-0.14550003380861354, -0.9999999999999986)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Cos
    >>> FloatField.register_lookup(Cos)
    >>> # Get vectors whose cosine is less than 0.5
    >>> vectors = Vector.objects.filter(x__cos__lt=0.5, y__cos__lt=0.5)

### `Cot`

class Cot(expression, **extra)

Renvoie la cotangente d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Cot
    >>> Vector.objects.create(x=12.0, y=1.0)
    >>> vector = Vector.objects.annotate(x_cot=Cot("x"), y_cot=Cot("y")).get()
    >>> vector.x_cot, vector.y_cot
    (-1.5726734063976826, 0.642092615934331)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Cot
    >>> FloatField.register_lookup(Cot)
    >>> # Get vectors whose cotangent is less than 1
    >>> vectors = Vector.objects.filter(x__cot__lt=1, y__cot__lt=1)

### `Degrees`

class Degrees(expression, **extra)

Convertit un champ ou une expression numérique de radians en degrés.

Exemple d’utilisation :

    >>> from django.db.models.functions import Degrees
    >>> Vector.objects.create(x=-1.57, y=3.14)
    >>> vector = Vector.objects.annotate(x_d=Degrees("x"), y_d=Degrees("y")).get()
    >>> vector.x_d, vector.y_d
    (-89.95437383553924, 179.9087476710785)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Degrees
    >>> FloatField.register_lookup(Degrees)
    >>> # Get vectors whose degrees are less than 360
    >>> vectors = Vector.objects.filter(x__degrees__lt=360, y__degrees__lt=360)

### `Exp`

class Exp(expression, **extra)

Renvoie la valeur de `e` (la base du logarithme naturel) élevé à la puissance du champ ou de l’expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Exp
    >>> Vector.objects.create(x=5.4, y=-2.0)
    >>> vector = Vector.objects.annotate(x_exp=Exp("x"), y_exp=Exp("y")).get()
    >>> vector.x_exp, vector.y_exp
    (221.40641620418717, 0.1353352832366127)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Exp
    >>> FloatField.register_lookup(Exp)
    >>> # Get vectors whose exp() is greater than 10
    >>> vectors = Vector.objects.filter(x__exp__gt=10, y__exp__gt=10)

### `Floor`

class Floor(expression, **extra)

Renvoie le plus grand nombre entier qui n’est pas plus grand que le champ ou l’expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Floor
    >>> Vector.objects.create(x=5.4, y=-2.3)
    >>> vector = Vector.objects.annotate(x_floor=Floor("x"), y_floor=Floor("y")).get()
    >>> vector.x_floor, vector.y_floor
    (5.0, -3.0)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Floor
    >>> FloatField.register_lookup(Floor)
    >>> # Get vectors whose floor() is greater than 10
    >>> vectors = Vector.objects.filter(x__floor__gt=10, y__floor__gt=10)

### `Ln`

class Ln(expression, **extra)

Renvoie le logarithme naturel d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Ln
    >>> Vector.objects.create(x=5.4, y=233.0)
    >>> vector = Vector.objects.annotate(x_ln=Ln("x"), y_ln=Ln("y")).get()
    >>> vector.x_ln, vector.y_ln
    (1.6863989535702288, 5.4510384535657)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Ln
    >>> FloatField.register_lookup(Ln)
    >>> # Get vectors whose value greater than e
    >>> vectors = Vector.objects.filter(x__ln__gt=1, y__ln__gt=1)

### `Log`

class Log(expression1, expression2, **extra)

Accepte deux champs ou expressions numériques et renvoie le logarithme du second en base du premier.

Exemple d’utilisation :

    >>> from django.db.models.functions import Log
    >>> Vector.objects.create(x=2.0, y=4.0)
    >>> vector = Vector.objects.annotate(log=Log("x", "y")).get()
    >>> vector.log
    2.0

### `Mod`

class Mod(expression1, expression2, **extra)

Accepte deux champs ou expressions numériques et renvoie le reste du premier divisé par le second (opération modulo).

Exemple d’utilisation :

    >>> from django.db.models.functions import Mod
    >>> Vector.objects.create(x=5.4, y=2.3)
    >>> vector = Vector.objects.annotate(mod=Mod("x", "y")).get()
    >>> vector.mod
    0.8

### `Pi`

class Pi(**extra)

Renvoie la valeur de la constante mathématique `π`.

### `Power`

class Power(expression1, expression2, **extra)

Accepte deux champs ou expressions numériques et renvoie la valeur du premier élevé à la puissance du second.

Exemple d’utilisation :

    >>> from django.db.models.functions import Power
    >>> Vector.objects.create(x=2, y=-2)
    >>> vector = Vector.objects.annotate(power=Power("x", "y")).get()
    >>> vector.power
    0.25

### `Radians`

class Radians(expression, **extra)

Convertit un champ ou une expression numérique de degrés en radians.

Exemple d’utilisation :

    >>> from django.db.models.functions import Radians
    >>> Vector.objects.create(x=-90, y=180)
    >>> vector = Vector.objects.annotate(x_r=Radians("x"), y_r=Radians("y")).get()
    >>> vector.x_r, vector.y_r
    (-1.5707963267948966, 3.141592653589793)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Radians
    >>> FloatField.register_lookup(Radians)
    >>> # Get vectors whose radians are less than 1
    >>> vectors = Vector.objects.filter(x__radians__lt=1, y__radians__lt=1)

### `Random`

class Random(**extra)

Renvoie une valeur aléatoire dans l’intervalle `0.0 ≤ x < 1.0`.

### `Round`

class Round(expression, precision=0, **extra)

Arrondit un champ ou une expression numérique à `precision` (doit être un entier) décimales. Par défaut, l’arrondi se fait vers l’entier le plus proche. L’arrondi vers le haut ou vers le bas des valeurs médianes (.5) dépend de la base de données utilisée.

Exemple d’utilisation :

    >>> from django.db.models.functions import Round
    >>> Vector.objects.create(x=5.4, y=-2.37)
    >>> vector = Vector.objects.annotate(x_r=Round("x"), y_r=Round("y", precision=1)).get()
    >>> vector.x_r, vector.y_r
    (5.0, -2.4)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Round
    >>> FloatField.register_lookup(Round)
    >>> # Get vectors whose round() is less than 20
    >>> vectors = Vector.objects.filter(x__round__lt=20, y__round__lt=20)

### `Sign`

class Sign(expression, **extra)

Renvoie le signe (-1, 0, 1) d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Sign
    >>> Vector.objects.create(x=5.4, y=-2.3)
    >>> vector = Vector.objects.annotate(x_sign=Sign("x"), y_sign=Sign("y")).get()
    >>> vector.x_sign, vector.y_sign
    (1, -1)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Sign
    >>> FloatField.register_lookup(Sign)
    >>> # Get vectors whose signs of components are less than 0.
    >>> vectors = Vector.objects.filter(x__sign__lt=0, y__sign__lt=0)

### `Sin`

class Sin(expression, **extra)

Renvoie le sinus d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Sin
    >>> Vector.objects.create(x=5.4, y=-2.3)
    >>> vector = Vector.objects.annotate(x_sin=Sin("x"), y_sin=Sin("y")).get()
    >>> vector.x_sin, vector.y_sin
    (-0.7727644875559871, -0.7457052121767203)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Sin
    >>> FloatField.register_lookup(Sin)
    >>> # Get vectors whose sin() is less than 0
    >>> vectors = Vector.objects.filter(x__sin__lt=0, y__sin__lt=0)

### `Sqrt`

class Sqrt(expression, **extra)

Renvoie la racine carrée d’un champ ou d’une expression numérique non négative.

Exemple d’utilisation :

    >>> from django.db.models.functions import Sqrt
    >>> Vector.objects.create(x=4.0, y=12.0)
    >>> vector = Vector.objects.annotate(x_sqrt=Sqrt("x"), y_sqrt=Sqrt("y")).get()
    >>> vector.x_sqrt, vector.y_sqrt
    (2.0, 3.46410)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Sqrt
    >>> FloatField.register_lookup(Sqrt)
    >>> # Get vectors whose sqrt() is less than 5
    >>> vectors = Vector.objects.filter(x__sqrt__lt=5, y__sqrt__lt=5)

### `Tan`

class Tan(expression, **extra)

Renvoie la tangente d’un champ ou d’une expression numérique.

Exemple d’utilisation :

    >>> from django.db.models.functions import Tan
    >>> Vector.objects.create(x=0, y=12)
    >>> vector = Vector.objects.annotate(x_tan=Tan("x"), y_tan=Tan("y")).get()
    >>> vector.x_tan, vector.y_tan
    (0.0, -0.6358599286615808)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import FloatField
    >>> from django.db.models.functions import Tan
    >>> FloatField.register_lookup(Tan)
    >>> # Get vectors whose tangent is less than 0
    >>> vectors = Vector.objects.filter(x__tan__lt=0, y__tan__lt=0)

## Fonctions textuelles

### `Chr`

class Chr(expression, **extra)

Accepte un champ ou une expression numérique et renvoie la représentation textuelle de l’expression sous forme de caractère unique. Il fonctionne comme la fonction `chr()` de Python.

Comme `Length`, il peut être inscrit comme transformation pour `IntegerField`. Le nom de requête par défaut est `chr`.

Exemple d’utilisation :

    >>> from django.db.models.functions import Chr
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.filter(name__startswith=Chr(ord("M"))).get()
    >>> print(author.name)
    Margaret Smith

### `Concat`

class Concat(*expressions, **extra)

Accepte une liste d’au moins deux champs textes ou expressions et renvoie la concaténation de ces paramètres. Chaque paramètre doit être de type texte ou caractère. Si vous voulez concaténer un champ `TextField()` avec un champ `CharField()`, prenez alors la précaution d’indiquer à Django que le résultat `output_field` sera un champ `TextField()`. C’est aussi nécessaire lors de la concaténation avec une valeur `Value` comme dans l’exemple ci-dessous.

Le résultat de cette fonction n’est jamais nul. Pour les moteurs où un paramètre nul aboutit à ce que toute l’expression devienne nulle, Django s’assure que chaque partie nulle est préalablement convertie en chaîne vide.

Exemple d’utilisation :

    >>> # Get the display name as "name (goes_by)"
    >>> from django.db.models import CharField, Value as V
    >>> from django.db.models.functions import Concat
    >>> Author.objects.create(name="Margaret Smith", goes_by="Maggie")
    >>> author = Author.objects.annotate(
    ...     screen_name=Concat("name", V(" ("), "goes_by", V(")"), output_field=CharField())
    ... ).get()
    >>> print(author.screen_name)
    Margaret Smith (Maggie)

### `Left`

class Left(expression, length, **extra)

Renvoie les n (`length`) premiers caractères du champ texte ou de l’expression donnée.

Exemple d’utilisation :

    >>> from django.db.models.functions import Left
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(first_initial=Left("name", 1)).get()
    >>> print(author.first_initial)
    M

### `Length`

class Length(expression, **extra)

Accepte un champ texte ou une expression unique et renvoie le nombre de caractères de la valeur. Si l’expression est nulle, la longueur renvoyée sera également nulle.

Exemple d’utilisation :

    >>> # Get the length of the name and goes_by fields
    >>> from django.db.models.functions import Length
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(
    ...     name_length=Length("name"), goes_by_length=Length("goes_by")
    ... ).get()
    >>> print(author.name_length, author.goes_by_length)
    (14, None)

Cette expression peut aussi être inscrite comme transformation. Par exemple :

    >>> from django.db.models import CharField
    >>> from django.db.models.functions import Length
    >>> CharField.register_lookup(Length)
    >>> # Get authors whose name is longer than 7 characters
    >>> authors = Author.objects.filter(name__length__gt=7)

### `Lower`

class Lower(expression, **extra)

Accepte un champ texte ou une expression unique et renvoie sa représentation en minuscules.

Cette expression peut aussi être inscrite comme transformation comme expliqué pour `Length`.

Exemple d’utilisation :

    >>> from django.db.models.functions import Lower
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(name_lower=Lower("name")).get()
    >>> print(author.name_lower)
    margaret smith

### `LPad`

class LPad(expression, length, fill_text=Value(' '), **extra)

Renvoie la valeur du champ texte ou de l’expression donnée remplie à sa gauche par `fill_text` afin que la longueur de la valeur résultante possède `length` caractères. La valeur par défaut de `fill_text` est un espace.

Exemple d’utilisation :

    >>> from django.db.models import Value
    >>> from django.db.models.functions import LPad
    >>> Author.objects.create(name="John", alias="j")
    >>> Author.objects.update(name=LPad("name", 8, Value("abc")))
    1
    >>> print(Author.objects.get(alias="j").name)
    abcaJohn

### `LTrim`

class LTrim(expression, **extra)

Semblable à `Trim`, mais n’enlève que les espaces de début de chaîne.

### `MD5`

class MD5(expression, **extra)

Accepte un champ texte ou une expression unique et renvoie l’empreinte MD5 de la chaîne.

Cette expression peut aussi être inscrite comme transformation comme expliqué pour `Length`.

Exemple d’utilisation :

    >>> from django.db.models.functions import MD5
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(name_md5=MD5("name")).get()
    >>> print(author.name_md5)
    749fb689816b2db85f5b169c2055b247

### `Ord`

class Ord(expression, **extra)

Accepte un seul champ texte ou une expression et renvoie la valeur du point de code Unicode du premier caractère de cette expression. Il fonctionne comme la fonction `ord()` de Python, mais aucune exception n’est générée si l’expression comporte plus d’un caractère.

Cette expression peut aussi être inscrite comme transformation comme expliqué pour `Length`. Le nom de requête par défaut est `ord`.

Exemple d’utilisation :

    >>> from django.db.models.functions import Ord
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(name_code_point=Ord("name")).get()
    >>> print(author.name_code_point)
    77

### `Repeat`

class Repeat(expression, number, **extra)

Renvoie la valeur du champ texte ou de l’expression indiquée répétée `number` fois.

Exemple d’utilisation :

    >>> from django.db.models.functions import Repeat
    >>> Author.objects.create(name="John", alias="j")
    >>> Author.objects.update(name=Repeat("name", 3))
    1
    >>> print(Author.objects.get(alias="j").name)
    JohnJohnJohn

### `Replace`

class Replace(expression, text, replacement=Value(''), **extra)

Remplace toutes les occurrences de `text` dans `expression` par `replacement`. Le texte de remplacement par défaut est la chaîne vide. Les paramètres de la fonction sont sensibles à la casse.

Exemple d’utilisation :

    >>> from django.db.models import Value
    >>> from django.db.models.functions import Replace
    >>> Author.objects.create(name="Margaret Johnson")
    >>> Author.objects.create(name="Margaret Smith")
    >>> Author.objects.update(name=Replace("name", Value("Margaret"), Value("Margareth")))
    2
    >>> Author.objects.values("name")
    <QuerySet [{'name': 'Margareth Johnson'}, {'name': 'Margareth Smith'}]>

### `Reverse`

class Reverse(expression, **extra)

Accepte un champ texte ou une expression unique et renvoie les caractères de cette expression en ordre inverse.

Cette expression peut aussi être inscrite comme transformation comme expliqué pour `Length`. Le nom de requête par défaut est `reverse`.

Exemple d’utilisation :

    >>> from django.db.models.functions import Reverse
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(backward=Reverse("name")).get()
    >>> print(author.backward)
    htimS teragraM

### `Right`

class Right(expression, length, **extra)

Renvoie les n (`length`) derniers caractères du champ texte ou de l’expression donnée.

Exemple d’utilisation :

    >>> from django.db.models.functions import Right
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(last_letter=Right("name", 1)).get()
    >>> print(author.last_letter)
    h

### `RPad`

class RPad(expression, length, fill_text=Value(' '), **extra)

Semblable à `LPad`, mais applique le remplissage en fin de chaîne.

### `RTrim`

class RTrim(expression, **extra)

Semblable à `Trim`, mais n’enlève que les espaces de fin de chaîne.

### `SHA1`, `SHA224`, `SHA256`, `SHA384` et `SHA512`

class SHA1(expression, **extra)

class SHA224(expression, **extra)

class SHA256(expression, **extra)

class SHA384(expression, **extra)

class SHA512(expression, **extra)

Accepte un champ texte ou une expression unique et renvoie l’empreinte correspondante de la chaîne.

Elles peuvent aussi être inscrites comme transformations comme expliqué pour `Length`.

Exemple d’utilisation :

    >>> from django.db.models.functions import SHA1
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(name_sha1=SHA1("name")).get()
    >>> print(author.name_sha1)
    b87efd8a6c991c390be5a68e8a7945a7851c7e5c

PostgreSQL

L”extension pgcrypto doit être installée. Vous pouvez utiliser l’opération de migration `CryptoExtension` pour l’installer.

Oracle

Oracle ne prend pas en charge la fonction `SHA224`.

### `StrIndex`

class StrIndex(string, substring, **extra)

Renvoie un nombre entier positif correspondant à la position indicée (commençant à 1) de la première occurrence de `substring` dans `string`, ou 0 si `substring` est introuvable.

Exemple d’utilisation :

    >>> from django.db.models import Value as V
    >>> from django.db.models.functions import StrIndex
    >>> Author.objects.create(name="Margaret Smith")
    >>> Author.objects.create(name="Smith, Margaret")
    >>> Author.objects.create(name="Margaret Jackson")
    >>> Author.objects.filter(name="Margaret Jackson").annotate(
    ...     smith_index=StrIndex("name", V("Smith"))
    ... ).get().smith_index
    0
    >>> authors = Author.objects.annotate(smith_index=StrIndex("name", V("Smith"))).filter(
    ...     smith_index__gt=0
    ... )
    <QuerySet [<Author: Margaret Smith>, <Author: Smith, Margaret>]>

Avertissement

Avec MySQL, la collation d’une table de base de données détermine si les comparaisons de chaînes (telles que dans `expression` et `substring` de cette fonction) sont sensibles à la casse. Par défaut, les comparaisons ne sont pas sensibles à la casse.

### `Substr`

class Substr(expression, pos, length=None, **extra)

Renvoie une sous-chaîne de longueur `length` extraite du champ ou de l’expression à partir de la position `pos`. L’indice de position commence à 1, il doit donc être plus grand que 0. Si `length` vaut `None`, tout le reste de la chaîne est renvoyé comme résultat.

Exemple d’utilisation :

    >>> # Set the alias to the first 5 characters of the name as lowercase
    >>> from django.db.models.functions import Lower, Substr
    >>> Author.objects.create(name="Margaret Smith")
    >>> Author.objects.update(alias=Lower(Substr("name", 1, 5)))
    1
    >>> print(Author.objects.get(name="Margaret Smith").alias)
    marga

### `Trim`

class Trim(expression, **extra)

Renvoie la valeur du champ texte ou de l’expression indiquée sans les espaces de début et de fin de chaîne.

Exemple d’utilisation :

    >>> from django.db.models.functions import Trim
    >>> Author.objects.create(name="  John  ", alias="j")
    >>> Author.objects.update(name=Trim("name"))
    1
    >>> print(Author.objects.get(alias="j").name)
    John

### `Upper`

class Upper(expression, **extra)

Accepte un champ texte ou une expression unique et renvoie sa représentation en majuscules.

Cette expression peut aussi être inscrite comme transformation comme expliqué pour `Length`.

Exemple d’utilisation :

    >>> from django.db.models.functions import Upper
    >>> Author.objects.create(name="Margaret Smith")
    >>> author = Author.objects.annotate(name_upper=Upper("name")).get()
    >>> print(author.name_upper)
    MARGARET SMITH

## Fonctions de fenêtrage

Il existe un certain nombre de fonctions à utiliser dans une expression `Window` pour calculer la position des éléments ou le `Ntile` de certaines lignes.

### `CumeDist`

class CumeDist(*expressions, **extra)

Calcule la distribution cumulative d’une valeur à l’intérieur d’une fenêtre ou d’une partition. La distribution cumulative est définie comme le nombre de lignes précédant ou apparentées à la ligne actuelle divisé par le nombre total de lignes dans l’intervalle.

### `DenseRank`

class DenseRank(*expressions, **extra)

Équivalent à `Rank` mais sans « trous ».

### `FirstValue`

class FirstValue(expression, **extra)

Renvoie la valeur évaluée à la ligne se situant en premier dans l’intervalle de fenêtre, ou `None` si une telle valeur n’existe pas.

### `Lag`

class Lag(expression, offset=1, default=None, **extra)

Calcule le décalage de valeur selon `offset`, et si aucune ligne n’existe à cet endroit, renvoie `default`.

`default` doit avoir le même type que `expression`; cependant, cette validation se fait dans la base de données et pas dans le code Python.

MariaDB et `default`

MariaDB ne prend pas en charge le paramètre `default`.

### `LastValue`

class LastValue(expression, **extra)

Comparable à `FirstValue`, renvoie la dernière valeur dans une clause d’intervalle donnée.

### `Lead`

class Lead(expression, offset=1, default=None, **extra)

Calcule la valeur de tête dans un intervalle donné. `offset` et `default` sont tous deux évalués en fonction de la ligne actuelle.

`default` doit avoir le même type que `expression`; cependant, cette validation se fait dans la base de données et pas dans le code Python.

MariaDB et `default`

MariaDB ne prend pas en charge le paramètre `default`.

### `NthValue`

class NthValue(expression, nth=1, **extra)

Calcule la ligne relative au décalage `nth` (la valeur doit être positive) à l’intérieur de la fenêtre. Renvoie `None` si aucune ligne ne correspond.

Certaines bases de données gèrent différemment une nième valeur inexistante. Par exemple, Oracle renvoie une chaîne vide au lieu de `None` pour les expressions basées sur des caractères. Django n’applique aucune conversion dans ces cas.

### `Ntile`

class Ntile(num_buckets=1, **extra)

Calcule une partition pour chacune des lignes dans la clause d’intervalle, distribuant les nombres aussi également que possible entre 1 et `num_buckets`. Si les lignes ne sont pas divisibles de manière égale par le nombre de « buckets », un ou plusieurs de ceux-ci seront représentés plus fréquemment.

### `PercentRank`

class PercentRank(*expressions, **extra)

Calcule le rang relatif des lignes dans la clause d’intervalle. Ce calcul est équivalent à l’évaluation de :

    (rank - 1) / (total rows - 1)

Le tableau suivant explique le calcul du rang relatif d’une ligne :

N° de ligne | Valeur | Rang | Calcul | Rang relatif
--- | --- | --- | --- | ---
1 | 15 | 1 | (1-1)/(7-1) | 0.0000
2 | 20 | 2 | (2-1)/(7-1) | 0.1666
3 | 20 | 2 | (2-1)/(7-1) | 0.1666
4 | 20 | 2 | (2-1)/(7-1) | 0.1666
5 | 30 | 5 | (5-1)/(7-1) | 0.6666
6 | 30 | 5 | (5-1)/(7-1) | 0.6666
7 | 40 | 7 | (7-1)/(7-1) | 1.0000

### `Rank`

class Rank(*expressions, **extra)

Comparable à :class:RowNumber`, cette fonction calcule le rang des lignes de la fenêtre. Le rang calculé comporte des trous. Utilisez `DenseRank` pour calculer le rang sans trous.

### `RowNumber`

class RowNumber(*expressions, **extra)

Calcule le numéro de ligne selon le tri de la clause d’intervalle ou selon le tri de toute la requête s’il n’y a pas partition dans l’intervalle de fenêtre.