我正在按照MDN的Express.js教程为odin项目的Nodejs项目清单创建清单应用程序。我可以删除项目,更新项目和读取项目,但是当我要创建项目时,会遇到错误(对于模型“项目”,在路径“ _id”的值“创建”对ObjectId的转换失败)。
我仔细阅读了所有代码,当尝试替换“ items_create_get”中的内容时,错误从未改变,这使我认为这不是问题所在。
//itemsController.js:
var Items = require("../models/items");
var async = require("async");
const { body, validationResult } = require("express-validator/check");
const { sanitizeBody } = require("express-validator/filter");
exports.items_create_post = [
// Convert the category to an array.
(req, res, next) => {
if (!(req.body.category instanceof Array)) {
if (typeof req.body.category === "undefined")
req.body.category = [];
else req.body.category = new Array(req.body.category);
}
next();
},
// Handle items create on POST.
exports.items_create_post = [
// Convert the category to an array.
(req, res, next) => {
if (!(req.body.category instanceof Array)) {
if (typeof req.body.category === "undefined")
req.body.category = [];
else req.body.category = new Array(req.body.category);
}
next();
},
// Validate fields.
body("name", "Name must not be empty.")
.isLength({ min: 1 })
.trim(),
body("description", "Description must not be empty.")
.isLength({ min: 1 })
.trim(),
body("price", "Price must not be empty.")
.isLength({ min: 1 })
.trim(),
body("num_in_stock", "Number in stock must not be empty")
.isLength({ min: 1 })
.trim(),
// Sanitize fields.
sanitizeBody("*").escape(),
sanitizeBody("category.*").escape(),
// Process request after validation and sanitization.
(req, res, next) => {
// Extract the validation errors from a request.
const errors = validationResult(req);
// Create a Items object with escaped and trimmed data.
var items = new Items({
name: req.body.name,
description: req.body.description,
category: req.body.category,
price: req.body.price,
num_in_stock: req.body.num_in_stock
});
if (!errors.isEmpty()) {
/* There are errors. Render form again with sanitized values/error messages.*/
// Get all categories for form.
async.parallel(
{
category: function(callback) {
Category.find(callback);
}
},
function(err, results) {
if (err) {
return next(err);
}
res.render("items_form", {
title: "Create Item",
category: results.category,
items: items,
errors: errors.array()
});
}
);
return;
} else {
// Data from form is valid. Save book.
items.save(function(err) {
if (err) {
return next(err);
}
// Successful - redirect to new items record.
res.redirect(items.url);
});
}
}
];
//items.js(Model):
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ItemsSchema = new Schema ({
name: {type: String, required: true, max: 100},
description: {type: String, required: true},
category: {type: Schema.Types.ObjectId, ref: 'Category', required: true},
price: {type: String, required: true},
num_in_stock: {type: String, required: true}
})
ItemsSchema.virtual('url').get(function() {
return '/catalog/items/' + this._id
});
module.exports = mongoose.model('Items', ItemsSchema);
//catalog.js (Router):
router.get('/items/create', items_controller.items_create_get);
router.post('/items/create', items_controller.items_create_post);
//items_form.pug(views):
extends layout
block content
h1= title
form(method='POST' action='')
div.form-group
label(for='name') Name:
input#name.form-control(type='text', placeholder='Name of item' name='name' required='true' value=(undefined===items ? '' : items.name) )
div.form-group
label(for='description') Description:
input#description.form-control(type='textarea', placeholder='Enter Description' name='description' value=(undefined===items ? '' : items.description) required='true' )
div.form-group
label(for='category') Category:
input#category.form-control(type='text', placeholder='Consumable, Tools or Accessories' name='category' value=(undefined===items ? '' : items.category.name) required='true' )
div.form-group
label(for='price') Price:
input#price.form-control(type='text', placeholder='Price: e.g. 20$' name='price' value=(undefined===items ? '' : items.price) required='true')
div.form-group
label(for='num_in_stock') Number in Stock:
input#num_in_stock.form-control(type='text', placeholder='num in stock: e.g. 2' name='num_in_stock' value=(undefined===items ? '' : items.num_in_stock) required='true')
button.btn.btn-primary(type='submit') Submit
if errors
ul
for error in errors
li!= error.msg
//Edit: catalog.js (Router):
// GET catalog home page.
router.get('/', items_controller.index);
// GET request for one Item.
router.get('/items/:id', items_controller.items_detail);
// GET request for list of all Item.
router.get('/items', items_controller.items_list);
router.get('/items/create', items_controller.items_create_get);
router.post('/items/create', items_controller.items_create_post);
// GET request to delete Item.
router.get('/items/:id/delete', items_controller.items_delete_get);
// POST request to delete Item.
router.post('/items/:id/delete',
items_controller.items_delete_post);
// GET request to update Item.
router.get('/items/:id/update', items_controller.items_update_get);
// POST request to update Item.
router.post('/items/:id/update',
items_controller.items_update_post);
这个问题也在我的类别模型中...
输出屏幕很好,所有其他CRUD视图都可以使用create控制器之外的其他功能...也许值得一提的是,当我更新项目时,items_form.js可以完美地工作! * /
答案 0 :(得分:0)
问题出在您的虚拟架构中,请尝试将其更改为:
ItemsSchema.virtual('url').get(function() {
return '/catalog/items/' + this._id.toString()
});
这是因为_id的类型为 ObjectId ,而您正在尝试将其与字符串连接。
希望这会有所帮助:)
答案 1 :(得分:0)
因为您放:
router.get('/items/:id', items_controller.items_detail);
之前:
router.get('/items/create', items_controller.items_create_get);
因此,当您呼叫/items/create
时,路由器将指向items_controller.items_detail
,而不是items_controller.items_create_get
,并获得create
作为参数id
。
更改路由器,将/items/:id
放在/items/create
之后可能会解决您的问题。