66 votes

Django "Impossible d'ajouter ou de mettre à jour une rangée enfant : une contrainte de clé étrangère échoue".

J'ai un modèle Coupon et un modèle Photo avec un ForeignKey à ce sujet :

class Photo(models.Model):
    coupon = models.ForeignKey(Coupon,
                               related_name='description_photos')
    title = models.CharField(max_length=100)
    image = models.ImageField(upload_to='images')

J'ai configuré des lignes dans l'administration et je peux maintenant ajouter des photos à un coupon depuis l'administration.

J'essaie d'en ajouter un, et le téléchargement est réussi, mais j'obtiens ensuite la page de débogage de Django avec cette erreur :

IntegrityError at /admin/coupon/coupon/321/
(1452, 'Cannot add or update a child row: a foreign key constraint fails (`my_project`.`coupon_photo`, CONSTRAINT `coupon_id_refs_id_90d7f06` FOREIGN KEY (`coupon_id`) REFERENCES `coupon_coupon` (`id`))')

Qu'est-ce que c'est et comment puis-je résoudre ce problème ?

(Si cela a de l'importance, il s'agit d'une base de données MySQL).

EDIT : J'ai essayé sur une base de données Sqlite3 qui a un jeu de données légèrement différent, et cela a fonctionné, donc peut-être qu'il y a des données perdues dans ma base de données actuelle ? Comment puis-je les trouver et les supprimer ?

86voto

Ram Rachum Points 10233

Certaines de mes tables étaient en InnoDB et d'autres en MyISAM... J'ai tout changé en MyISAM et le problème a été résolu.

71voto

mmrs151 Points 1041
DATABASES = {
'default': {
    ...         
    'OPTIONS': {
         "init_command": "SET foreign_key_checks = 0;",
    },
 }
}

( Selon le document officiel ) Dans les versions précédentes de Django, les fichiers fixes avec des références à venir (c'est-à-dire des relations avec des lignes qui n'ont pas encore été insérées dans la base de données) ne se chargeaient pas lorsqu'ils utilisaient le moteur de stockage InnoDB. Cela était dû au fait qu'InnoDB s'écarte de la norme SQL en vérifiant les contraintes de clé étrangère immédiatement au lieu de différer la vérification jusqu'à ce que la transaction soit validée. Ce problème a été résolu dans Django 1.4.

19voto

ApPeL Points 1919

Pour éviter que cela ne se produise, vous pouvez également définir votre STORAGE_ENGINE dans votre settings.py

pour django >= 1.2

DATABASES = {
    'default': {
        ...
        'STORAGE_ENGINE': 'MyISAM / INNODB / ETC'
    }
}

pour django <= 1.2

DATABASE_STORAGE_ENGINE = "MyISAM / INNODB / ETC"

Veuillez noter que ceci n'est valable que pour MySQL

4voto

supervacuo Points 4236

Je me suis heurté au même problème : la solution de mmrs151 fonctionne, mais NB que, pour Django <= 1.2 ( c'est-à-dire avant la prise en charge de plusieurs bases de données), le paramètre ressemble à ceci :

DATABASE_OPTIONS = {"init_command": "SET foreign_key_checks = 0;"}

Il est intéressant de noter que Ram Rachum semble avoir contourné le problème plutôt que de le résoudre : MyISAM ne supporte pas du tout les transactions...

-3voto

Une autre option consiste à supprimer la contrainte dans votre table MySQL :

alter table <TABLE_NAME> drop foreign key <CONTRAINT_NAME>;

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