如何使用强大的包和猫鼬处理 POST 结果?

How to handle POST results with formidable package and mongoose?

我做了一些关于使用 node.js 处理 POST 请求的研究,所以现在可以用了。 我也知道如何使用猫鼬将新的 JSON object 保存到 mongoDB collection。 我觉得我已经接近解决方案,但我很难找到答案。

具体问题

现在,我需要一些帮助来将这两个放在一起。

处理 POST 请求 [ok+-] => 转换为 JSON object/mongoose object [不行] = > 保存到 collection [ok+-]

控制器代码

这是我正在使用的代码。基本功能有效:

代码:

// controller function for adding a ressource
var post = function(req, res){
  // incoming form
  var form = new formidable.IncomingForm();
  var fields = {};

  console.dir('ceci est bien un post');
  // everytime an field is parsed...
  // This is the place where I should do validation and throw errors if needed
  form.on('field', function (field, value) {
      console.log(field);
      console.log(value);
      fields[field] = value;
  });


  // Once the form is parsed completely
  form.on('end', function () {
      // testing the output
      var ressources = util.inspect(fields, {showHidden: false, depth: null});
      console.dir(util.inspect(fields, {showHidden: false, depth: null}));

      // here save it in mongodb collection
      var ressource = new Ressource(fields);

      // ressource.save(function (err, ressource, isSuccess) {
      //       if (err) {
      //         res.status(400);
      //         res.send('Error occured ' + err);
      //       }
      //       else if (isSuccess === 1) {
      //         res.status(201);
      //         res.send(ressource);
      //       } 
      //       else {
      //         res.status(400);
      //       }
      //     });

      // rendering the page with the results
      res.render('addRessourceView', {
                  title: 'Ressources',
                  fields: ressources
              });
  });

  form.parse(req);
};

这是猫鼬模型:

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var ressourceModel = new Schema({
  title: { type: String },
  descr_short: { type: String },
  m_visual: { type: Boolean, default: false },
  m_writing:{ type: Boolean, default: false },
  m_moving: { type: Boolean, default: false },
  m_speaking:{ type: Boolean, default: false },
  m_music:{ type: Boolean, default: false },
  age: String,
  minAge: { type: Number }, 
  maxAge: { type: Number }, 
  prerequisite:{ type: Array,
            items: { type: String },
            uniqueItems:  true},
  language: { type: String },
  source: { type: String },
  intra_identify: { type: Boolean, default: false },
  intra_expression: { type: Boolean, default: false },
  intra_comprehension: { type: Boolean, default: false },
  intra_regulation: { type: Boolean, default: false },
  intra_utilisation: { type: Boolean, default: false },
  theme_impulsivity: { type: Boolean, default: false },
  theme_violence: { type: Boolean, default: false },
  inter_identify: { type: Boolean, default: false },
  inter_expression: { type: Boolean, default: false },
  inter_comprehension: { type: Boolean, default: false },
  inter_regulation: { type: Boolean, default: false },
  inter_utilisation: { type: Boolean, default: false },
  details:{ 
    type: Object,
    properties: {
      goals: {  type: Array,
                items: { type: String },
                uniqueItems:  true},
      preparation: String,
      exercices: {  type: Array,
                    items: { type: Object }},
      reflexion: String
    }
  },
  upload:{  type: Array,
          items: { type: Object }}
});

module.exports = mongoose.model('Ressource', ressourceModel);

注意:"boolean" 的所有内容都是复选框输入

所以所有这些字段也在表单中(我只是没有实现文件上传)。 所以基本上我需要帮助的是:

我真的是来学习的,我只是一个初学者,我尽量把我的问题说清楚,希望大家能帮帮我!

谢谢, Xogno

昨天,我花了一整天的时间来处理它,我来让它按我想要的方式工作!其实,多研究了一点,其实并不难:只是需要一些好的逻辑和花时间去做。

免责声明 :我正在使用 'formidable' 包来处理 post 请求,并学会了将其与 [=16] 一起使用=].

我首先从添加结构和注释开始,只是为了写下我的代码背后的逻辑思维。然后我开始一个一个地实现每个字段的代码。 form.on('field'....){} 每次解析一个字段时都会执行,所以我就是这样一个一个地处理它们的。为此,我使用了 switch(true) 和倍数 cases ... : ... break; 。 我添加了需要的验证,给对象添加了错误,这样所有的字段都一个一个添加到一个JSON对象中。

关于错误,我在 html 页面中使用 EJS 模板显示了它们。

然后,一旦一切正常(处理 POST 字段和处理错误),我唯一要做的就是将它链接(保存)到 mongodb 集合,使用 .save 来自猫鼬的方法。

所以这一切都发生在服务器端,而不是动态发生。也许稍后我会重新编码它以动态工作,使用 ajax 或其他一些框架(Vue.js?),所以它不需要重新加载整个页面并且会更有效率。

这是代码,希望对某些人有所帮助!


处理 post 请求的代码

form.on('field') // 逐一处理每个字段

form.on('field', function (field, value) {
        console.log(field);
        console.log(value);



        switch (true) {
            //check if title is not empty, if empty, throw error
            case field === 'title':
                if(value == ''){
                        // then error
                        console.log('titre vide')
                        fields.error = ['title-empty'];
                        fields[field] = value;
                    }
                    else{
                        fields.error = [];
                        fields[field] = value;
                    }
                break;
            // check if description is not empty
            case field === 'short_descr':
                if(value == ''){
                        // then error
                        console.log('titre vide')
                        fields.error = ['descr-empty'];
                        fields[field] = value;
                    }
                    else{
                        fields[field] = value;
                    }
                break;
            // when receiving minAge or maxAge, save it as number
            case (field === 'minAge' || field === 'maxAge') :
                if(field === 'maxAge'){
                    var maxAge = value;
                    if(Number(maxAge) < Number(fields.minAge)){
                        // then error
                        console.log('Error :  maxAge plus petit que minAge')
                        fields.error.push('maxAge<minAge');
                    }
                }
                fields[field] = Number(value);
                break;
            // if 'objectives'
            case field === 'objectives':
                console.log('hey we have an objectif!')
                // when receiving an objective, verify if there's already one
                if('objectives' in fields.details){
                    //then there is already an objective object
                    console.log('adding an objective to the list');
                    fields.details[field].push(value);
                } 
                // then we create the objective entry in fields.details
                else {

                    fields.details[field] = [value];
                    console.log('ajouté aux détails');
                }

                break;
            // if 'materials'
            case field === 'materials':
                console.log('hey we have an material!')
                // when receiving an objective, verify if there's already one
                if('materials' in fields.details){
                    //then there is already an objective object
                    console.log('adding an material to the list');
                    fields.details[field].push(value);
                } 
                // then we create the objective entry in fields.details
                else {

                    fields.details[field] = [value];
                    console.log('ajouté aux détails');
                }

                break;
            // when receiving an exercice, verify if there's already an exercice that exists
            // if there's already an exercice that exists, and this one isn't null, add this one as another exercice
            // verify also if ex_time is a number
            // and insert it under 'details.exercices' (array of objects : {ex_descr: '', ex_time:''})
            // renvoyer une erreur si le temps est vide ou si pas un nombre
            case field === 'exercices':
                console.log('hey we have an exercice!')
                // when receiving an objective, verify if there's already one
                //first check if it's not empty

                if('exercices' in fields.details){
                    if(value === ''){
                        //it's empty, add an error
                        fields.error.push('Empty-' + field + '[' + j + ']');
                        console.log('exercice is empty');
                    }

                    //then there is already an objective object
                    console.log('adding an exercice to the list');
                    var object_exercices = {};
                    object_exercices.ex = value;
                    fields.details.exercices.push(object_exercices);
                    j++;

                } 
                // then we create the objective entry in fields.details
                else {
                    if(value === ''){
                        //it's empty, add an error
                        fields.error.push('Empty-' + field + '[' + j + ']');
                        console.log('exercice is empty');
                    }

                    var object_exercices = {};
                    object_exercices.ex = value;
                    fields.details.exercices = [object_exercices];
                    console.log('ajouté aux détails');
                    j++;
                }

                break;

            //if it's an exercice_time we need to add it to the exercice object in the exercice array
            case field === 'exercices-time':
                console.log('hey we have an exercice-time!')
                // when receiving an exercice-time, verify if there's already an exercice existing
                if ('exercices' in fields.details){
                    if(isNaN(value) || value === ''){
                        // if it's not a number, push a new error
                        fields.error.push('NaNexercice_time[' + i + ']');
                        console.log('but its not a number or is empty ' + i);

                        //recuparate the object of the exercice
                        var object_exercices = {};
                        object_exercices = fields.details.exercices[i];
                        object_exercices.exercice_time = value;
                        // add the value of ex_time to it
                        fields.details.exercices[i] = object_exercices;
                        i++;
                    } else {
                    // if it's a number
                    // and then there is already an exercice object
                    console.log('adding an exercice-time to the last exercice ' + i);

                    //recuparate the object of the exercice
                    var object_exercices = {};
                    object_exercices = fields.details.exercices[i];
                    object_exercices.exercice_time = Number(value);
                    // add the value of ex_time to it
                    fields.details.exercices[i] = object_exercices;
                    i++;
                    }
                }

                break;

            // if "preparation" add it to details.preparation
            case field === 'preparation':

                fields.details[field] = value;
                console.log('ajouté aux détails');
                break;

            case field === 'intra_identification' || field === 'intra_regulation' || field === 'intra_understanding' 
                || field === 'intra_utilisation' || field === 'intra_expression' || field === 'inter_identification' 
                || field === 'inter_expression' || field === 'inter_utilisation' || field === 'inter_regulation' 
                || field === 'inter_understanding':

                //to see if they've at least checked one competence
                fields[field] = value;

                break;

            // otherwise it's a basic input
            default:
                fields[field] = value;
        }
    });

form.on('end') // 一旦整个表单被解析

// Once the form is parsed completely
    form.on('end', function () {
        // last error handling

        //test if they've at least added one competence
        if(!fields.intra_identification && !fields.intra_regulation 
        && !fields.intra_understanding && !fields.intra_utilisation 
        && !fields.intra_expression && !fields.inter_identification 
        && !fields.inter_expression && !fields.inter_utilisation 
        && !fields.inter_regulation && !fields.inter_understanding) {
            fields.error.push('No competence selected');
                            console.log('No competence selected');
        }

        // testing the output
            console.dir(util.inspect(fields, {showHidden: false, depth: null}));

        //time to save
        // see if there were errors
        if(fields.error.length < 1){
            //no errors
            //then save it in the database
            console.log('no errors');

            // save it in mongodb collection
            var ressource = new Ressource(fields);

            ressource.save(function (err, ressource, isSuccess) {
                  if (err) {
                    res.status(400);
                    //res.send('Error occured ' + err);
                    res.render('addRessourceView', {
                                title: 'Ressources',
                                fields: fields,
                                saved: false
                            });
                  }
                  else if (isSuccess === 1) {
                    res.status(201);
                    //res.send(ressource);
                        // render the page with save success
                        res.render('addRessourceView', {
                                title: 'Ressources',
                                fields: fields,
                                saved: true
                            });
                  } 
                  else {
                    res.status(400);
                    res.render('addRessourceView', {
                                title: 'Ressources',
                                fields: fields,
                                saved: false
                            });
                  }
                });


        } else {
            console.dir(fields.error);

            // render the page with save success
            res.render('addRessourceView', {
                    title: 'Ressources',
                    fields: fields,
                    saved: false
                });
        }


    });
    form.parse(req);