L'option related_name dans Django ORM est un paramètre de champ qui apparaît fréquemment lors de la définition de relations ForeignKey ou One-to-One. Au début, on peut facilement l'ignorer, mais plus le projet grandit, plus le besoin de related_name se fait sentir. Dans cet article, nous allons comprendre le concept et le rôle de related_name, et explorer les problèmes qui se posent si l'on ne l'utilise pas.


1. Exemples de références directe et inverse

Tout d'abord, voyons rapidement la différence entre référence directe et inverse à travers un exemple de code simple. Par exemple, supposons qu'il existe un modèle Post et un modèle Comment dans un système de blog. Le modèle Comment fait référence au modèle Post via une clé étrangère.

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    content = models.TextField()

Dans le code ci-dessus, le champ post du modèle Comment est une référence directe. Dans ce cas, pour référencer l'objet Post depuis l'objet Comment, on peut utiliser la syntaxe suivante.

comment = Comment.objects.first()
print(comment.post.title)  # Référence directe : accès de l.comment à l'article

En revanche, la référence inverse pour consulter Comment depuis Post peut être effectuée en utilisant le <nom du modèle>_set généré automatiquement par Django.

post = Post.objects.first()
print(post.comment_set.all())  # Référence inverse : accès de l'article aux commentaires

Cependant, le nom généré automatiquement comment_set n'est pas intuitif et peut entraîner des conflits de noms lors de l'utilisation de relations multiples. Pour résoudre ce problème, on utilise related_name.


2. Pourquoi est-il nécessaire d'utiliser related_name?

Le related_name joue un rôle crucial pour clarifier les relations entre les modèles dans Django et améliorer la lisibilité du code. Plus un projet est important, plus il devient essentiel de gérer les relations entre les modèles de manière intuitive. Les principales raisons pour lesquelles related_name est nécessaire sont les suivantes :

  • Limites du nom de base _set
    Si on ne spécifie pas related_name, Django génère automatiquement un nom de référence inverse à partir de _set. Par exemple, pour accéder aux commentaires dans le modèle Post, il faut utiliser post.comment_set. Toutefois, comment_set n'est pas intuitif et nuit à la lisibilité du code. Si l'on définit related_name="comments", on peut alors se référer à post.comments, un nom beaucoup plus clair.
  • Prévention de la confusion dans les relations multiples
    Lorsque un modèle réfère à un même modèle par plusieurs champs avec des clés étrangères, related_name devient indispensable. Par exemple, lorsque le modèle Post fait référence à l'auteur et à l'éditeur via le modèle User. Si on utilise _set sans related_name, les noms de référence inverse se chevauchent et entraînent des erreurs.

3. Exemple de configuration related_name : amélioration de la lisibilité et de la clarté

Voici un exemple redéfini des modèles Post et Comment avec l'application de related_name.

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)

class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="comments")
    content = models.TextField()

À présent, lors de la référence inverse de Comment à partir de Post, on peut y accéder via post.comments. En définissant le nom de manière claire, la relation devient intuitive, améliorer la lisibilité et la maintenabilité du code.

post = Post.objects.first()
print(post.comments.all())  # Référence avec `comments`

4. related_name pour les relations multiples

Dans une situation où un modèle fait plusieurs références au même modèle, la configuration de related_name est essentielle. Prenons l'exemple où le modèle Post réfère à l'auteur et à l'éditeur à travers le modèle User.

class User(models.Model):
    username = models.CharField(max_length=50)

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="authored_posts")
    editor = models.ForeignKey(User, on_delete=models.CASCADE, related_name="edited_posts")

Ici, en spécifiant respectivement related_name="authored_posts" et related_name="edited_posts", il devient possible de référencer clairement les articles écrits et édités par le modèle User.

user = User.objects.first()
print(user.authored_posts.all())  # Articles écrits
print(user.edited_posts.all())    # Articles édités

5. Utilisation de related_name dans une relation de référence à soi-même

Il arrive que l'on ait besoin d'utiliser related_name pour établir une relation self-referential au sein d'un modèle. Par exemple, on peut faire en sorte que le modèle Employee référence son propre supérieur afin d'exprimer la relation de hiérarchie dans une organisation.

class Employee(models.Model):
    name = models.CharField(max_length=100)
    manager = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL, related_name="subordinates")

Dans ce cas, en définissant related_name="subordinates", il est possible de référencer intuitivement les subordonnés avec employee.subordinates.


6. Importance du related_name dans une relation One-to-One

Dans une relation One-to-One, related_name reste tout aussi important pour les mêmes raisons. Par exemple, lorsque le modèle User est lié au modèle Profile dans une relation 1:1, définir related_name permet de mieux gérer cette relation.

class User(models.Model):
    username = models.CharField(max_length=50)

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")

Désormais, on peut accéder au Profile via user.profile, ce qui rend la relation intuitive et facile à maintenir.


7. Résumé et introduction rapide à related_query_name

  • related_name est une option qui permet de définir clairement les références inverses des relations ForeignKey et One-to-One dans Django ORM.
  • Elle résout les désagréments liés au nom de base _set et réduit la confusion dans les relations multiples ou de référence à soi-même.
  • Dans les relations One-to-One ou self-referential, elle aide également à rendre le code plus intuitif.

Dans le prochain article, nous aborderons brièvement l'option related_query_name. Cette option, similaire à related_name, permet de définir les relations de référence mais s'avère utile dans le filtrage ou les conditions de requête. C'est une option visant à améliorer l'utilisabilité dans l'ORM, donc restez à l'affût pour le prochain article.