Clé étrangère auto-référentielle Django

166

Je suis un peu nouveau dans les applications Web et les bases de données en général, donc cela pourrait être une question stupide. Je veux créer un modèle ("CategoryModel") avec un champ qui pointe vers l'identifiant principal d'une autre instance du modèle (son parent).

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

Comment puis-je faire cela? Merci!

sfendell
la source
2
Stylistiquement, je suggérerais d'appeler ceci parentau lieu de parentId, puisque ce my_category_model.parentsera une instance de CategoryModel. Django créera automatiquement un membre parent_idqui sera la clé primaire du modèle associé.
10flow

Réponses:

263

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

Alors:

parent = models.ForeignKey("CategoryModel")

Ou vous pouvez utiliser la chaîne "self"

parent = models.ForeignKey("self")
Jared Forsyth
la source
55

Vous pouvez utiliser la chaîne «self» pour indiquer une auto-référence.

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

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

Brandon
la source
7
Je pense que tu veux dire «soi». Comme dans la chaîne. soi n'est pas défini dans ce contexte
Jared Forsyth
1
@Brandon En quoi le «soi» dans votre réponse est-il différent de ce que Jared a dit dans son commentaire? "Je pense que tu veux dire" soi "!!! . Les deux sont des chaînes, ce qui est bien selon la documentation de django. ! Tous les indices
Stryker
1
La différence est que cela selfn'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 la __init__()ou d'une autre méthode, ce serait, comme selftoujours, le premier argument de position de toute méthode d'instance d'une classe Python.
Brandon
1

Vous devez également définir null = True et vide = True

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

null = True, pour autoriser dans la base de données
vide = True, pour autoriser la validation du formulaire

Punnerud
la source