Node+express项目,提交表单信息时Cannot read property '_id' of undefined

前言

这是我在学习imooc上node实战时遇到的问题,视频中老师用了以下代码

var app = express()

var express = require('express')

app.use(express.bodyParser())

最后在视频中运行无误。

已解决的问题

我已经知道express.bodyParser()在新版本中被取消
图片描述

也知道了替代方案中的extend:true的作用
图片描述

仍然存在的问题

可是当我把代码修正过来之后,仍然报错

修改的代码

var bodyParser = require('body-parser')

app.use(bodyParser.urlencoded({ extended: true }))//将表单数据格式化

报错

^[{ [ValidationError: Movie validation failed]

message: 'Movie validation failed',

name: 'ValidationError',

errors:

{ year:

{ [CastError: Cast to Number failed for value "2015/12/31" at path "year"]

message: 'Cast to Number failed for value "2015/12/31" at path "year"',

name: 'CastError',

kind: 'Number',

value: '2015/12/31',

path: 'year',

reason: undefined } } }

/Users/Vagor/Desktop/easy_movie/app.js:123

res.redirect('/movie/' + movie._id)

^

TypeError: Cannot read property '_id' of undefined

at /Users/Vagor/Desktop/easy_movie/app.js:123:37

at /Users/Vagor/Desktop/easy_movie/node_modules/mongoose/lib/document.js:1747:19

at handleError (/Users/Vagor/Desktop/easy_movie/node_modules/hooks-fixed/hooks.js:40:22)

at _next (/Users/Vagor/Desktop/easy_movie/node_modules/hooks-fixed/hooks.js:46:22)

at fnWrapper (/Users/Vagor/Desktop/easy_movie/node_modules/hooks-fixed/hooks.js:186:18)

at /Users/Vagor/Desktop/easy_movie/node_modules/mongoose/lib/schema.js:234:13

at complete (/Users/Vagor/Desktop/easy_movie/node_modules/mongoose/lib/document.js:1131:7)

at /Users/Vagor/Desktop/easy_movie/node_modules/mongoose/lib/document.js:1160:20

at ObjectId.SchemaType.doValidate (/Users/Vagor/Desktop/easy_movie/node_modules/mongoose/lib/schematype.js:654:22)

at /Users/Vagor/Desktop/easy_movie/node_modules/mongoose/lib/document.js:1156:9

at nextTickCallbackWith0Args (node.js:433:9)

at process._tickCallback (node.js:362:13)

出错的区块代码

app.post('/admin/movie/new', function(req, res) {

var id = req.body.movie._id

var movieObj = req.body.movie

var _movie

if (id !== 'undefined') {

Movie.findById(id, function(err, movie) {

if (err) {

console.log(err)

}

_movie = _.extend(movie, movieObj)

_movie.save(function(err, movie) {

if (err) {

console.log(err)

}

res.redirect('/movie/' + movie._id)

})

})

}

else {

_movie = new Movie({

doctor: movieObj.doctor,

title: movieObj.title,

country: movieObj.country,

language: movieObj.language,

year: movieObj.year,

poster: movieObj.poster,

summary: movieObj.summary,

flash: movieObj.flash

})

_movie.save(function(err, movie) {

if (err) {

console.log(err)

}

res.redirect('/movie/' + movie._id)

})

}

})

整个app.js代码

var express = require('express')

var port = 3000

var path = require('path')

var bodyParser = require('body-parser')

var _ = require('underscore')

var mongoose = require('mongoose')

var Movie = require('./models/movie.js')

var app = express()

mongoose.connect('mongodb://localhost/imooc')

app.set('views','./views/pages')

app.set('view engine','jade')

// app.use(express.bodyParser())

// app.use(bodyParser.urlencoded())

app.use(bodyParser.urlencoded({ extended: true }))//将表单数据格式化

app.use(express.static(path.join(__dirname,'bower_components')))//告诉浏览器请求样式就到此文件夹查找,dirname就是当前目录

app.listen(port)

app.locals.moment = require('moment')

console.log('imooc started on port:' + port)

//index page

app.get('/',function(req,res){

Movie.fetch(function(err,movies){

if (err) {

console.log(err)

}

res.render('index',{

title:'imovie 首页',

movies:movies

})

})

})

//detail page

app.get('/movie/:id',function(req,res){

var id = req.params.id

Movie.findById(id, function(err,movie){

if (err) {

console.log(err)

}

res.render('detail',{

title:'imovie' + movie.title,

movie:movie

})

})

})

//admin page

app.get('/admin/movie',function(req,res){

res.render('admin',{

title:'imovie 后台录入页',

movie:{

title: '',

doctor: '',

country: '',

year: '',

language: '',

summary: '',

poster: '',

flash: ''

}

})

})

//admin update movie

app.get('/admin/update/:id',function(req,res){

var id = req.params.id

if (id) {

Movie.findById(id,function(err,movie){

res.render('admin',{

title:'imovie 后台更新页',

movie:movie

})

})

}

})

//admin post movie

// admin post movie

app.post('/admin/movie/new', function(req, res) {

var id = req.body.movie._id

var movieObj = req.body.movie

var _movie

if (id !== 'undefined') {

Movie.findById(id, function(err, movie) {

if (err) {

console.log(err)

}

_movie = _.extend(movie, movieObj)

_movie.save(function(err, movie) {

if (err) {

console.log(err)

}

res.redirect('/movie/' + movie._id)

})

})

}

else {

_movie = new Movie({

doctor: movieObj.doctor,

title: movieObj.title,

country: movieObj.country,

language: movieObj.language,

year: movieObj.year,

poster: movieObj.poster,

summary: movieObj.summary,

flash: movieObj.flash

})

_movie.save(function(err, movie) {

if (err) {

console.log(err)

}

res.redirect('/movie/' + movie._id)

})

}

})

//list page

app.get('/admin/list',function(req,res){

Movie.fetch(function(err,movies){

if (err) {

console.log(err)

}

res.render('list',{

title:'imovie 列表页',

movies:movies

})

})

})

//list delete movie

app.delete('/admin/list',function(req,res){

var id = req.query.id

if (id) {

Movie.remove({_id:id},function(err,movie){

if (err) {

console.log(err)

}

else{

res.json({success:1})

}

})

};

})

情各位指出错误的根源并指正,谢谢!

问题休正及补充

当我submit(post方式)表单数据为数字时,可以提交并返回,但仍有文件传输错误。
图片描述

但是当我提交的是字符串(或者说是中文时,我不知道是什么原因),就会产生上述错误,服务器被强制关闭
图片描述
图片描述

我已经将代码上传至github,希望各位能帮我查看一下问题

回答:

除了bodyParser(urlencoded()),还需要一个bodyParser(json()),把Express升级到4.x使用生成器生成一个项目就知道了。

回答:

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

回答:

看了下代码逻辑上没有问题,但是缺少安全验证.主要问题是你发送请求的id不对啊,正确的Object_id的格式是24个字符的16进制数,例如:568761de48b492fd35046a45.程序崩溃的原因就是没有做url地址栏的校验.因为在正常情况下,客户端传递的id参数是从后台获取的ObjectId,但是为了严谨性现在做以下处理:

 var id = req.params.id;

if (id.match(/^[0-9a-fA-F]{24}$/)) {

Notice.findById(id, function(err, notice) {

if (err) {

res.json({

no: 0,

msg: '获取失败:' + err

});

} else {

var result = {

no: 1

};

result.obj = notice;

res.json(result);

}

});

} else {

res.json({

error: true,

msg: id + '不存在'

});

}

回答:

遇到一模一样的问题了,请问你是怎么解决啊,困扰我两天了

回答:

楼主报的错是 [{ [ValidationError: Movie validation failed],传入的数据跟没没有通过 Movie 的属性验证。

楼主在写路由的时候,如果有 err,请务必要使用 return,比如楼主 _movie.save(),需要写成下面的形式,否则出现错误会把自己看懵掉。

_movie.save(function(err, movie) {

if (err) return console.log(err);

// ...

});

回答:

mogoose的 model.save(function(err){}) 的回调参数只有 err 一个吧

http://mongoosejs.com/docs/models.html Constructing documents这一节

_id在new的时候已经生成了。
所以写成下面这样:

_movie.save(function(err) {

if (err) {

console.log(err)

// 这边应该跳转至错误页面

return res.redirect('/some/error/handler/page/' + err + JSON. stringify(_movie));

}

res.redirect('/movie/' + _movie._id);

})

回答:

不知道题主解决问题了没~
我也遇到了相同的问题。
不过最后发现是admin.jade的缩进有问题
如果题主还没解决问题的话可以试一下(●'◡'●)

回答:

其实你可以不用着急贴一大堆代码,先追踪下你的数据就知道了哪里有问题了。错误提示很明显是你用的东西没有_id这个字段,那你就查看下你当前用的东西到底是什么就可以了。当数据从数据库出来就开始追踪,控制台输出看下数据结构和类型。然后每次对数据有操作都看一下数据的结构和类型是否变化了。最后只要追踪到你出问题的地方就可以了,看看输出的到底是不是你想要的东西。

以上是 Node+express项目,提交表单信息时Cannot read property '_id' of undefined 的全部内容, 来源链接: utcz.com/p/196777.html

回到顶部