Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème de clés étrangères avec l'ORM Sequelize

Impossible de créer un model Post qui référencie un autre model User

Sujet résolu
    10 avril 2024 à 18:52:09

    Bonjour  tous:)

    Voici le code de mon model `User` qui lui est bien créé en base de données lors de l'initialisation de mon application

    const validRoles = ['admin', 'normal'];
    
    // Creation d'un model User pour la table users
    module.exports = (sequelize, DataTypes) => {
        return sequelize.define(
            // Nom du model
            'User',
            // Champs
            {
                user_id: {
                    type: DataTypes.INTEGER,
                    primaryKey: true,
                    autoIncrement: true
                },
                username: {
                    type: DataTypes.STRING,
                    allowNull: false,
                    validate: {
                        notEmpty: {
                            msg: 'Le nom d\'utilisateur ne doit pas être vide !'
                        },
                        notNull: {
                            msg: 'Le nom d\'utilisateur est requis !'
                        }
                    }
                },
                user_email: {
                    type: DataTypes.STRING,
                    allowNull: false,
                    unique: {
                        msg: 'Ce nom d\'utilisateur est dejà prit !'
                    },
                    validate: {
                        isEmail: {
                            msg: 'L\'email n\'est pas valide !'
                        },
                        notNull: {
                            msg: 'L\'email est requis !'
                        }
                    }
                },
                user_password: {
                    type: DataTypes.STRING,
                    allowNull: false
                },
                user_role: {
                    type: DataTypes.STRING,
                    allowNull: false,
                    validate: {
                        isRoleValid(role) {
                            if(!role) {
                              throw new Error('Un utilisateur doit avoir un rôle !')
                            }
                            if(!validRoles.includes(role)) {
                                throw new Error(`Le type d'un pokémon doit appartenir à la liste suivante : ${validRoles}`)
                            }
                        }
                    }
                }
            },
            // timestamps
            {
                timestamps: true
            }



    Et voici celui du model Post qui pose problème

    const { gzipSync, gunzipSync } = require('zlib');
    
    // Creation d'un model Post pour la table posts
    module.exports = (sequelize, DataTypes) => {
        return sequelize.define(
            // Nom du model
            'Post',
            // Champs
            {
                post_id: {
                    type: DataTypes.INTEGER,
                    primaryKey: true,
                    autoIncrement: true
                },
                user_id: {
                    type: DataTypes.INTEGER,
                    references: {
                        model: 'User',
                        key: `user_id`
                    }
                },
                post_text: {
                    type: DataTypes.TEXT,
                    allowNull: false,
                    validate: {
                        notEmpty: {
                            msg: 'Le contenu ne doit pas être vide !'
                        }
                    },
                    get() {
                        const storedValue = this.getDataValue('content');
                        const gzippedBuffer = Buffer.from(storedValue, 'base64');
                        const unzippedBuffer = gunzipSync(gzippedBuffer);
                        return unzippedBuffer.toString();
                    },
                    set(value) {
                        const gzippedBuffer = gzipSync(value);
                        this.setDataValue('content', gzippedBuffer.toString('base64'));
                    }
                },
                post_image: {
                    type: DataTypes.STRING
                },
                post_content: {
                    type: DataTypes.VIRTUAL,
                    get() {
                        return `${this.post_text} + ' ' + ${this.post_image}`;
                    },
                    set(value) {
                        throw new Error('Do not try to set the `post_content` value!');
                    }
                }
            },
            // timestamps
            {
                timestamps: true
            }
        );
    }


    Quant au message d'erreur, le voici


      original: SqlError: (conn:100, no: 1005, SQLState: HY000) Can't create table `groupomania`.`Posts` (errno: 150 "Foreign key constraint is incorrectly formed")
      sql: CREATE TABLE IF NOT EXISTS `Posts` (`post_id` INTEGER auto_increment , `user_id` INTEGER, `post_text` TEXT NOT NULL, `post_image` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`post_id`), FOREIGN KEY (`user_id`) R... - parameters:[]
          at module.exports.createError (/home/victorin/workspace/On going/groupomania_api/node_modules/mariadb/lib/misc/errors.js:66:10)
          at PacketNodeEncoded.readError (/home/victorin/workspace/On going/groupomania_api/node_modules/mariadb/lib/io/packet.js:576:19)
          at Query.readResponsePacket (/home/victorin/workspace/On going/groupomania_api/node_modules/mariadb/lib/cmd/parser.js:62:28)
          at PacketInputStream.receivePacketBasic (/home/victorin/workspace/On going/groupomania_api/node_modules/mariadb/lib/io/packet-input-stream.js:85:9)
          at PacketInputStream.onData (/home/victorin/workspace/On going/groupomania_api/node_modules/mariadb/lib/io/packet-input-stream.js:135:20)
          at Socket.emit (node:events:514:28)
          at addChunk (node:internal/streams/readable:545:12)
          at readableAddChunkPushByteMode (node:internal/streams/readable:495:3)
          at Readable.push (node:internal/streams/readable:375:5)
          at TCP.onStreamRead (node:internal/stream_base_commons:190:23) {
        sqlMessage: 'Can\'t create table `groupomania`.`Posts` (errno: 150 "Foreign key constraint is incorrectly formed")',
        sql: 'CREATE TABLE IF NOT EXISTS `Posts` (`post_id` INTEGER auto_increment , `user_id` INTEGER, `post_text` TEXT NOT NULL, `post_image` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`post_id`), FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`)) ENGINE=InnoDB;',
        fatal: false,
        errno: 1005,
        sqlState: 'HY000',
        code: 'ER_CANT_CREATE_TABLE',
        parameters: undefined
      },
      sql: 'CREATE TABLE IF NOT EXISTS `Posts` (`post_id` INTEGER auto_increment , `user_id` INTEGER, `post_text` TEXT NOT NULL, `post_image` VARCHAR(255), `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, PRIMARY KEY (`post_id`), FOREIGN KEY (`user_id`) REFERENCES `User` (`user_id`)) ENGINE=InnoDB;',
      parameters: {}
    }
    


    Merci de bien vouloir m'aider:)


    • Partager sur Facebook
    • Partager sur Twitter
      11 avril 2024 à 11:02:04

      il est questions d'une table "Posts" alors que le nom du modèle est "Post" au singulier, et les champs de date de création et de mise à jour ne semblent pas présent.

      La table User est bien créée avant la table Post? (et est-ce que son nom est bien User et pas Users ?)

      -
      Edité par umfred 11 avril 2024 à 11:09:27

      • Partager sur Facebook
      • Partager sur Twitter
        11 avril 2024 à 12:59:06

        En fait la convention de Sequelize c'est d'utiliser le nom des models au pluriel pour créer les tables ( par exemple le model Post devient une table Posts en base de données ) donc là n'est pas le problème...

        En plus le model User a bien généré une table Users en base de données puis oui la table Users est créée avant la table Posts

        -
        Edité par Vivo13 11 avril 2024 à 13:00:21

        • Partager sur Facebook
        • Partager sur Twitter
          11 avril 2024 à 16:27:38

          Donc l'erreur est dans le nom indiqué de la table pour la clé étrangère, que l'on voit appelé User (au singulier) dans la requête au lieu de l'avoir "traduit" en Users (au pluriel)

          On peut peut-être passer par le nom du modèle User ou sinon, a priori la méthode recommandée, il faut passer par l'ajout de la contrainte via une association (one-to-many, one-to-one, one-to-many) en dehors de la définition du modèle

           https://sequelize.org/docs/v6/core-concepts/assocs/ 

          • Partager sur Facebook
          • Partager sur Twitter

          Problème de clés étrangères avec l'ORM Sequelize

          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
          • Editeur
          • Markdown