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
¶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
¶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
¶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
¶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
¶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)
La possibilité d’inscrire la fonction en tant que transformation a été ajoutée.
Lower
¶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
La possibilité d’inscrire la fonction en tant que transformation a été ajoutée.
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())
[<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
¶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
¶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
La possibilité d’inscrire la fonction en tant que transformation a été ajoutée.
août 01, 2016