如何使用强大的包和猫鼬处理 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+-]
控制器代码
这是我正在使用的代码。基本功能有效:
处理字段 posted 和 "saving" 到 object
渲染字段 posted ("fields" object)
代码:
// 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" 的所有内容都是复选框输入
所以所有这些字段也在表单中(我只是没有实现文件上传)。
所以基本上我需要帮助的是:
- 将 post 字段调整为我可以与 mongoose 一起使用的内容并保存它
- 也许对如何添加一些验证有帮助(比如确保 minAge 小于 maxAge,或其他东西)
- 如果您有时间或愿意,如何处理文件上传
我真的是来学习的,我只是一个初学者,我尽量把我的问题说清楚,希望大家能帮帮我!
谢谢,
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);
我做了一些关于使用 node.js 处理 POST 请求的研究,所以现在可以用了。 我也知道如何使用猫鼬将新的 JSON object 保存到 mongoDB collection。 我觉得我已经接近解决方案,但我很难找到答案。
具体问题
现在,我需要一些帮助来将这两个放在一起。
处理 POST 请求 [ok+-] => 转换为 JSON object/mongoose object [不行] = > 保存到 collection [ok+-]
控制器代码
这是我正在使用的代码。基本功能有效:
处理字段 posted 和 "saving" 到 object
渲染字段 posted ("fields" object)
代码:
// 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" 的所有内容都是复选框输入
所以所有这些字段也在表单中(我只是没有实现文件上传)。 所以基本上我需要帮助的是:
- 将 post 字段调整为我可以与 mongoose 一起使用的内容并保存它
- 也许对如何添加一些验证有帮助(比如确保 minAge 小于 maxAge,或其他东西)
- 如果您有时间或愿意,如何处理文件上传
我真的是来学习的,我只是一个初学者,我尽量把我的问题说清楚,希望大家能帮帮我!
谢谢, 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);