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,希望各位能帮我查看一下问题
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
除了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,但是为了严谨性现在做以下处理:遇到一模一样的问题了,请问你是怎么解决啊,困扰我两天了
楼主报的错是
[{ [ValidationError: Movie validation failed]
,传入的数据跟没没有通过Movie
的属性验证。楼主在写路由的时候,如果有
err
,请务必要使用return
,比如楼主_movie.save()
,需要写成下面的形式,否则出现错误会把自己看懵掉。mogoose的
model.save(function(err){})
的回调参数只有err
一个吧http://mongoosejs.com/docs/models.html Constructing documents这一节
_id
在new的时候已经生成了。所以写成下面这样:
不知道题主解决问题了没~
我也遇到了相同的问题。
不过最后发现是admin.jade的缩进有问题
如果题主还没解决问题的话可以试一下(●'◡'●)
其实你可以不用着急贴一大堆代码,先追踪下你的数据就知道了哪里有问题了。错误提示很明显是你用的东西没有_id这个字段,那你就查看下你当前用的东西到底是什么就可以了。当数据从数据库出来就开始追踪,控制台输出看下数据结构和类型。然后每次对数据有操作都看一下数据的结构和类型是否变化了。最后只要追踪到你出问题的地方就可以了,看看输出的到底是不是你想要的东西。