Fonctions de base de données

New in Django 1.8.

Les classes documentées ci-dessous permettent d’exploiter dans Django les fonctions fournies par la base de données sous-jacente telles que les annotations, les agrégations ou les filtres. Les fonctions sont également des expressions, elles peuvent donc être utilisées et combinées avec d’autres expressions comme les fonctions d’agrégation.

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.

Coalesce

class Coalesce(*expressions, **extra)[source]

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, Value as V
>>> 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
>>> aggregated = Author.objects.aggregate(
...    combined_age=Coalesce(Sum('age'), V(0)),
...    combined_age_default=Sum('age'))
>>> print(aggregated['combined_age'])
0
>>> print(aggregated['combined_age_default'])
None

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.expressions import RawSQL
>>> from django.utils import timezone
>>> now = timezone.now()
>>> now_sql = RawSQL("cast(%s as datetime)", (now,))
>>> Coalesce('updated', now_sql)

Concat

class Concat(*expressions, **extra)[source]

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)

Greatest

class Greatest(*expressions, **extra)[source]
New in Django 1.9.

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)[source]
New in Django 1.9.

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.

Length

class Length(expression, **extra)[source]

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, 'length')
>>> # Get authors whose name is longer than 7 characters
>>> authors = Author.objects.filter(name__length__gt=7)
Changed in Django 1.9:

La possibilité d’inscrire la fonction en tant que transformation a été ajoutée.

Lower

class Lower(expression, **extra)[source]

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
Changed in Django 1.9:

La possibilité d’inscrire la fonction en tant que transformation a été ajoutée.

Now

class Now[source]
New in Django 1.9.

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

Substr

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

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 Substr, Lower
>>> 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

Upper

class Upper(expression, **extra)[source]

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
Changed in Django 1.9:

La possibilité d’inscrire la fonction en tant que transformation a été ajoutée.

Back to Top