231 votes

Clé étrangère autoréférentielle de Django

Je suis un peu novice en matière d'applications web et de bases de données en général, donc il se peut que cette question soit stupide. Je veux créer un modèle ("CategoryModel") avec un champ qui pointe vers l'identifiant primaire d'une autre instance du modèle (son parent).

class CategoryModel(models.Model):
    parent = models.ForeignKey(CategoryModel)

Comment faire ? Merci de votre réponse.

3 votes

D'un point de vue stylistique, je suggérerais d'appeler cela parent au lieu de parentId puisque my_category_model.parent sera une instance de CategoryModel . Django créera automatiquement un membre parent_id qui sera la clé primaire du modèle apparenté.

370voto

Jared Forsyth Points 2655

Vous pouvez transmettre le nom d'un modèle sous forme de chaîne de caractères à ForeignKey et il fera ce qu'il faut.

Ainsi :

parent = models.ForeignKey("CategoryModel")

Vous pouvez également utiliser la chaîne "self"

parent = models.ForeignKey("self")

2 votes

Comment gérer l'instance racine si l'on ne met pas null=True / blank = True ?

6 votes

@zypro vous ne pouvez pas. Vous DEVEZ faire en sorte qu'il soit nullable.

3 votes

parent = models.ForeignKey("self") plus lisible

80voto

Brandon Points 11873

Vous pouvez utiliser la chaîne "self" pour indiquer une autoréférence.

class CategoryModel(models.Model):
    parent = models.ForeignKey('self')

https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

12 votes

Je pense que vous voulez dire "soi". Comme dans la chaîne de caractères. self n'est pas défini dans ce contexte.

1 votes

@Brandon En quoi le terme "self" dans votre réponse diffère-t-il de ce qu'a dit Jared dans son commentaire ? Je pense que vous voulez dire "soi" ! !! . Les deux sont des chaînes de caractères, ce qui est correct d'après les docs de django. ! Un conseil ?

6 votes

La différence est que self n'est pas présent lors de la définition de la propriété du modèle. Si la propriété était définie dans le cadre de l'élément __init__() ou une autre méthode, ce serait, comme self est toujours le premier argument d'une méthode d'instance d'une classe Python.

22voto

Punnerud Points 362

Vous devez également définir null=True y blank=True

class CategoryModel(models.Model):
    parent = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True)

null=True pour permettre l'accès à la base de données
blank=True pour permettre la validation du formulaire

8voto

Hailee Points 69

https://books.agiliq.com/projects/django-orm-cookbook/en/latest/self_fk.html

class Employee(models.Model):
    manager = models.ForeignKey('self', on_delete=models.CASCADE)

OU

class Employee(models.Model):
    manager = models.ForeignKey("app.Employee", on_delete=models.CASCADE)

https://stackabuse.com/recursive-model-relationships-in-django/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X