web-dev-qa-db-fra.com

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

J'ai un modèle Coupon, et un modèle Photo avec un ForeignKey:

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 mis en place des inlines dans l'administrateur alors maintenant je peux ajouter des photos à un coupon de l'administrateur.

J'essaie d'en ajouter un et le téléchargement est réussi, mais je reçois 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 est important, il s'agit d'une base de données MySQL.)

EDIT: Je l'ai essayé sur une base de données Sqlite3 qui a un ensemble de données légèrement différent, et cela a fonctionné, alors peut-être qu'il y a des données en vrac dans ma base de données actuelle? Comment puis-je le trouver et le supprimer?

65
Ram Rachum

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

86
Ram Rachum
DATABASES = {
'default': {
    ...         
    'OPTIONS': {
         "init_command": "SET foreign_key_checks = 0;",
    },
 }
}

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

67
mmrs151

Pour éviter cela, 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 cela n'est valable que pour MySQL

19
ApPeL

J'ai rencontré ce même problème: la solution de mmrs151 fonctionne, mais NB cela, 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 convient de noter que Ram Rachum semble avoir contourné plutôt que résolu le problème: MyISAM ne prend pas en charge les transactions du tout ...

4
supervacuo

Parfois, la raison de cette erreur est d'essayer d'enregistrer d'abord la table enfant, puis d'enregistrer le parent.
La solution pour cela utilise.

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

2). Vérifiez le flux d'opérations de votre base de données et faites-le parent ---> child

4
GrvTyagi